- 前缀和
前缀和主要适用的场景是原始数组不会被修改的情况下,频繁查询某个区间的累加和。
模板一般这么写:
class PrefixSum{
private:
vector<int> prefix;
public:
PrefixSum(vector<int>& arr){
prefix.reserve(arr.size());
//下标从0到n-1
prefix[0]=arr[0];
for(int i=1;i<prefix.size();++i){
prefix[i]=prefix[i-1]+arr[i];
}
}
int query(int i, int j){
//下标从0到n-1
if(i==0){
return prefix[j];
}
return prefix[j]-prefix[i-1];
}
};
- 差分数组
「差分数组」和前缀和的策略十分相似,差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减。
生成差分数组
diff[0]=arr[0]; for(int i=1;i<arr.size();++i){ diff[i]=arr[i]-arr[i-1]; }
**
借助diff进行区间修改,将区间修改的时间复杂度将到O(1)。
这样构造差分数组diff
,就可以快速进行区间增减的操作,如果你想对区间nums[i..j]
的元素全部加 3,那么只需要让diff[i] += 3
,然后再让diff[j+1] -= 3
即可:
void rangeIncresement(int i, int j, int value){
diff[i]+=value;
if(j+1<diff.size()){
diff[j+1]-=value;
}
}
- 根据差分数组重构原数组:
最后,模板为:vector<int> ret(diff.size(),0); ret[0]=diff[0]; for(int i=1;i<ret.size();++i){ ret[i]=ret[i-1]+diff[i]; } return ret;
class DiffRange{ private: vector<int> diff; public: DiffRange(vector<int>& arr){ diff.reserve(arr.size()); diff[0]=arr[0]; for(int i=1;i<arr.size();++i){ diff[i]=arr[i]-arr[i-1]; } } void rangeIncresement(int i, int j, int value){ diff[i]+=value; if(j+1<diff.size()){ diff[j+1]-=value; } } vector<int> getResult(){ vector<int> ret(diff.size(),0); ret[0]=diff[0]; for(int i=1;i<ret.size();++i){ ret[i]=ret[i-1]+diff[i]; } return ret; } };
- 二维前缀数组 Leetcode 1074