前缀和算法实战:和为 K 的子数组
问题描述
今天我们来聊聊经典的「和为 K 的子数组」问题。题目要求在一个整数数组中,找出所有和为给定值 K 的连续子数组的数量。

核心要点
- 子数组必须是数组元素的连续非空排列。
- 数组元素可能包含正数、负数和零。这一点非常关键,它直接决定了我们能否使用滑动窗口等常见技巧。
解题思路
暴力解法的局限
最直观的想法是枚举所有可能的子数组,计算它们的和并与 K 比较。这需要三层循环:两层确定左右边界,一层求和。时间复杂度高达 O(N³),对于稍大的数据量显然无法接受。
为什么滑动窗口行不通?
之前做过的双指针或滑动窗口题目,往往依赖窗口信息的单调性来降低遍历复杂度。比如只有正数时,右指针移动和会增大,左指针移动和会减小。
但本题数组中包含 0 和负数,导致求和结果不再具有单调性。我们无法通过简单的指针移动来保证窗口内和的变化趋势,因此双指针的思路在这里只能放弃。
前缀和 + 哈希表
对于数组求和问题,我们还有一个强有力的工具:前缀和。
我们可以将数组抽象成一条折线,方便观察区间关系。假设当前遍历到位置 i,其前缀和为 sum[i]。如果存在一个起始位置 j(j < i),使得从 j+1 到 i 的子数组和为 K,那么必然满足:
sum[i] - sum[j] = K
即:
sum[j] = sum[i] - K
这意味着,只要我们在遍历过程中,能够快速统计出之前出现过多少次等于 sum[i] - K 的前缀和,就能知道以当前位置结尾、和为 K 的子数组有多少个。
核心逻辑
- 维护前缀和:遍历数组时累加当前元素得到
current_sum。 - 查找匹配:在哈希表中查找是否存在键值为
current_sum - K。如果存在,说明之前有若干位置的前缀和与当前位置构成和为 K 的子数组,累加对应的次数。 - 更新哈希表:将当前的
current_sum记录到哈希表中,供后续位置查询使用。


