![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/911bba0693576b2888ac5cb21cff2b9c.png)
1 前缀和(未经哈希表优化)
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int count = 0;
int size = nums.size();
// 前缀和数组
vector<int> pre(size + 1, 0);
// 计算前缀和数组的值
for (int i = 0; i < size; i++)
pre[i + 1] = pre[i] + nums[i];
// if sum[i,j] == k, then count++;
for (int i = 0; i < size; i++)
for (int j = i; j < size; j++)
if (pre[j + 1] - pre[i] == k) count++;
return count;
}
};
2 前缀和 + 哈希表优化
如上图所示,当遍历到nums[5] = 1
时,对应前缀和为13
,此时由pre[j + 1] - k == pre[i]
推断,遍历到nums[j + 1]
时只要找出有几个相同的pre[i]
即可,数量即表示子数组个数
上图中pre[6] = 13
,则左侧13 - 5 == 8
的个数即为当前子数组的个数2,若后续再出现1次13,则继续累加count,应为2+2=4
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int count = 0;
int size = nums.size();
// 哈希表记录从<前缀和, 出现频数>
unordered_map<int, int> sum2cnt;
// 关键:初始化pre_sum = 0时次数为1
sum2cnt[0] = 1;
int sum = 0;
for (int i = 0; i < size; i++) {
sum += nums[i];
// sum - pre_sum == k推导而来
int pre_sum = sum - k;
// 若前缀和存在,则直接累加该前缀和的出现频数
if (sum2cnt.count(pre_sum))
count += sum2cnt[pre_sum];
sum2cnt[sum]++;
}
return count;
}
};