https://leetcode-cn.com/problems/subarray-sum-equals-k/solution/de-liao-yi-wen-jiang-qian-zhui-he-an-pai-yhyf/
图形参照上图,公式不用上面的上面的有错位。
思路
我们求数列的和时,Sn = a1+a2+a3+…an; 此时Sn就是数列的前 n 项和。
例 S5 = a1 + a2 + a3 + a4 + a5; S2 = a1 + a2。所以我们完全可以通过 S5-S2 得到 a3+a4+a5 的值,
创建一个数组保存前N项和,前缀和数组preSum,这样我们可以快速得到某个区间的和。
比如我们要得到num[2]到num[4]之前的和,那么我们可以使用preSum[4]-preSum[1]
然后我们使用map来找每个值前面的值
模板
560题举例
int subarraySum(vector<int>& nums, int k) {
int count = 0;
//创建前缀和数组
vector<int> preSum(nums.size());
preSum[0] = nums[0];
for (int i = 1; i < nums.size(); i++) {
preSum[i] = nums[i] + preSum[i-1];
}
//得到前缀和数组之后,我们要求的题目就很简单了,就是前缀数组中两个数的差是否为K。其实就是两数之和的思路,但是这里map存储的是前缀和和出现的次数
map<int,int> m; //存前缀数组元素和对应出现的次数
m[0]++;//添加一个0,因为某个前缀和和0也能组成一个
//遍历前缀数组,如果当前数
for(int i = 0; i < preSum.size(); i++) {
int target = preSum[i] - k;
//如果在map中找到了该数,则
if(m.find(target) != m.end()) {
count += m[target];
}
//不管找没找到都次数加一
m[preSum[i]]++;
}
return count;
}
-
- 寻找数组的中心下标
-
- 和为K的子数组(map存储<前缀和,出现次数>)
-
- 和相同的二元子数组(同560)
-
- 和可被 K 整除的子数组(注意取余数方式和map存储的值)