LeetCode:560 974 数组前缀和
做子数组的连续和的问题,可以首先考虑滑动窗口;如果滑动窗口不好用,可以使用这里的前缀和。
前缀和甚至能够解决二维数组中区间和的问题。
前缀和的一个总结见链接:
https://blog.csdn.net/weixin_43462819/article/details/100731522
另外还有使用前缀和的子数组的连续和:303:https://leetcode.com/problems/range-sum-query-immutable/
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
unordered_map<int, int> m;//first为前缀和(从第一个开始一直加到现在的),second为数目
int sum = 0;
int ret = 0;
m[0] = 1;//这应该是自己检查的时候发现sum为k的时候出现问题然后添加上去的。含义是前缀和为0,至少有一种情况,就是什么都不包含
for(int i = 0; i < nums.size(); ++i) {
sum += nums[i];
if(m.find(sum-k) != m.end())
ret += m[sum-k];
m[sum]++;
}
return ret;
}
};
需要注意的就是说:我们迭代到其中一个数的时候,map当中已经包含了从零到它前面各个位置的前缀和。然后又会遍历所有位置,所以是对的。
class Solution {
public:
int subarraysDivByK(vector<int>& A, int K) {
unordered_map<int, int> m;//first为前缀和(从第一个加到现在的这个)除K的余数,如果为负数,加上K
int sum = 0;
int cnt = 0;
m[0] = 1;
for(int i = 0; i < A.size(); ++i) {
sum += A[i];
int temp = sum % K;
if(temp < 0)
temp += K;
if(m.find(temp) != m.end())
cnt += m[temp];
m[temp]++;
}
return cnt;
}
};
值得注意的是,余数可能为负数,这种情况下,需要加上K。也就是说,比如K为5,那么如果余数为-1,我们需要将它变为4。这样它产生的效果才是一样的。
这里的启发是:使用前缀和方法,存的不一定是前缀和,根据实际情况存下一些东西,但是应该都是根据前缀和计算出来的。比如这里的余数就是根据前缀和计算出来的。