前缀和算法实战:和为 K 的子数组与和可被 K 整除的子数组
前缀和是处理子数组求和问题的经典技巧。通过哈希表记录历史状态,我们可以将暴力枚举的 O(n²) 优化至 O(n)。本文将深入探讨两个高频考点:和为 K 的子数组,以及和可被 K 整除的子数组。
01. 和为 K 的子数组
题目描述: 给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续子数组的个数。

核心思路
设 sum[i] 表示从索引 0 到 i 的前缀和。如果我们要找以 i 结尾、和为 k 的子数组,就需要找到一个起始位置 x,使得 sum[i] - sum[x-1] = k。变换一下公式,即 sum[x-1] = sum[i] - k。
这意味着,我们不需要真的去维护一个完整的前缀和数组,只需要在遍历过程中,用一个哈希表记录每个前缀和出现的次数。当计算到当前位置的前缀和 currentSum 时,直接查询哈希表中 currentSum - k 出现过多少次,累加即可。
注意细节: 初始化时
hash[0] = 1。这代表前缀和为 0 的情况出现了一次(即空数组),用于处理从索引 0 开始就满足条件的情况。
代码实现
C++ 实现
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
unordered_map<int, int> hash;
// 细节:前缀和为 0 的情况需要预先计数
hash[0] = 1;
int sum = 0, ret = 0;
for (auto x : nums) {
sum += x; // 计算当前位置的前缀和
// 如果存在 sum - k,说明找到了符合条件的子数组
if (hash.count(sum - k)) {
ret += hash[sum - k];
}
// 更新当前前缀和的出现次数
hash[sum]++;
}
ret;
}
};



