前缀和与差分数组
前言
:对于一些枚举算法题当中,往往会涉及到时间复杂度太高而无法AC的情况
利用前缀和的方法可以以空间换时间,是对一些枚举题当中很重要的优化算法。
下面介绍两常用的性质上用来辅助的算法
一维前缀和
核心思路:前缀和->前n项的和=前n+1项和减去第n+1项
例题应用
随机给定L和R两个整数,返回Arrays这个整数数组中第L个元素到第R个元素之和
常规代码(时间复杂度O(n*随机给定的次数))
int sum;
for(int i=L;i<R;i++){
sum+=Arrays[i];
}
return sum;
前缀和优化(时间复杂度将降为为线性,空间复杂度增加)
预处理:sum[i]=sum[i-1]+Arrays[i];//得到一维前缀和
int[] sum
sum[0]=Arrays[0];
for(int i=1;i<Arrays.length;i++){
sum[i]=sum[i-1]+Arrays[i];//得到一维前缀和
}
return sum[R]-sum[L-1];
差分数组
一维差分数组
预处理:与前缀和相同,差分数组需要进行预处理
即dis[i]=a[i]-a[i-1]
即dis数组中存放的是a数组相邻的两个数字的差值。
这里我们设a[0]=0;
则a[i]利用递推思想(和高中的数组求和有点像哈)
可求得a[i]=dis[1]+dis[2]+…dis[i];
例题:现在有一个长度为n的数字序列(首项为0),现在要对他进行区间修改(将区间的所有数加上一个数),你需要输出修改m次后得到的序列是什么,需要你涉及一个O(m)的算法
for(int i=1;i<a.length;i++){
dis[i]=a[i]-a[i-1];//预处理
}
while(m--){*//操作次数*
cin>>left>>right>>change;*//左右端点及其变化的值*
d[left]+=change;
d[right+1]-=change;
}
for(int i=1;i<=a.length;i++){
a[i]=dis[i]+a[i-1];
}
总结差分数组用途:
既然我们要对区间进行修改,那么差分数组的作用一定就是求多次进行区间修改后的数组
注意 只能是区间元素同时增加或减少相同的数的情况才能使用。