前前缀和是一种重要的预处理,能大大降低查询的时间复杂度。
引入差分
差分:表示当前数字与上一个数字的差值
差分数组即是讲这一系列差分值放入一个数组。
举个例子,定义数组a为
int a[10]={0,2,4,5,6,10,3,7,8,9};
那么差分数组dif的值为
2 2 1 1 4 -7 4 1 1
前缀和
前缀和,即利用一个数组sum来记录数组a前i项的和。
可用来求区间和,如求数组a在区间[L,R]的和,那么就是将a[L] 和 a[R] 之间的所有的数相加,但是如果提前知道前L项的和sum[L] 以及前R项的和 sum[R],那么所求的结果就是 sum[L] - sum[R]。这里sum[L] 以及sum[R] 就是前缀和。(leetcode的560题)
利用前缀和可以极大的降低区间查询的时间复杂度
LeetCode相关题目
560. 和为K的子数组
题目目标是:找到该数组中和为 k 的连续的子数组的个数
那么重点就是找到和为k的连续子数组
假设在区间[left, right]中的数组元素的和为k,那么利用前缀和中的sum数组,即sum[right] - sum[left] = k,然后扫描整个数组,利用map存储 sum[left] 出现的个数,加上sum[right]-k作为出现过的前n项和的个数,然后更新统计量即可。
class Solution {
public:
//本题中不需要把sum的值存到数组中,只需要用map计算出现次数即可
int subarraySum(vector<int>& nums, int k) {
int res = 0;
int sum = 0;
//在map中初始化一对键值对{0,1}
unordered_map<int,int> mp{{0,1}};
for(int i = 0; i <nums.size();++i){
//更新当前sum[right]
sum += nums[i];
//更新统计量,sum-k即为sum[left]
res += mp[sum - k];
//统计sum出现次数
mp[sum]++;
}
return res;
}
};