给你一个整数数组 nums
和一个整数 k
,请你统计并返回 该数组中和为 k
的子数组的个数 。
子数组是数组中元素的连续非空序列。
示例 1:
输入:nums = [1,1,1], k = 2 输出:2
示例 2:
输入:nums = [1,2,3], k = 3 输出:2
提示:
1 <= nums.length <= 2 * 104
-1000 <= nums[i] <= 1000
-107 <= k <= 107
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
unordered_map<int,int> m;
m[0]=1;
int s,ans=0;
for(int n:nums){
s += n;
if(m.find(s-k) != m.end()){
ans+=m[s-k];
}
m[s]++;
}
return ans;
}
};
如果有两个前缀和 sum(i)
和 sum(j)
,那么sum(j) - sum(i) = k
则表示子数组从 i+1
到 j
的和为 k
哈希表 m
来记录每个前缀和的出现次数。
m[0] = 1
是为了处理一种特殊情况:假设从数组的第一个元素开始就有子数组和为 k
。
对于每一个前缀和 s
,我们检查哈希表 m
中是否存在 s - k
这个值。
对于每个新出现的 sum(j)
,我们检查是否有一个 sum(i)
使得 sum(j) - sum(i) = k
,即 sum(j) - k
是否已经出现过。如果出现过,说明从某个位置到当前位置的子数组和为 k
,我们就能增加结果计数。
实例:
nums = [1, 2, 3], k = 3
-
初始化:
m = {0: 1}
,s = 0
,ans = 0
-
第一次迭代 (
i = 0
,num = 1
):s = 0 + 1 = 1
- 查找
s - k = 1 - 3 = -2
,没有找到。 - 更新哈希表:
m = {0: 1, 1: 1}
-
第二次迭代 (
i = 1
,num = 2
):s = 1 + 2 = 3
- 查找
s - k = 3 - 3 = 0
,找到了,m[0] = 1
,所以ans += 1
。 - 更新哈希表:
m = {0: 1, 1: 1, 3: 1}
-
第三次迭代 (
i = 2
,num = 3
):s = 3 + 3 = 6
- 查找
s - k = 6 - 3 = 3
,找到了,m[3] = 1
,所以ans += 1
。 - 更新哈希表:
m = {0: 1, 1: 1, 3: 1, 6: 1}
最终结果:ans = 2
,表示有 2 个子数组和为 3,分别是 [1, 2]
和 [3]
。