给你一个整数数组 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]。
