现在有数组a[7]
int a[7];
a[0]=1;
a[1]=2;
a[2]=4;
a[3]=5;
a[4]=12
a[5]=34;
a[6]=123;
a[7]=3;
如果要把a[0]-a[4]都加一,最朴素的方法就是
a[0]++;
a[1]++;
a[2]++;
a[3]++;
a[4]++;
时间复杂度为O(n)
打字打着都很费力
但是如果先有一个神奇的差分数组d[7],就可以省力得多了!
现在开一个d[7]
int d[7];
d[0]=a[0];
d[1]=a[1]-a[0];
d[2]=a[2]-a[1];
d[3]=a[3]-a[2];
d[4]=a[4]-a[3];
d[5]=a[5]-a[4];
d[6]=a[6]-a[5];
d[7]=a[7]-a[6];
也可以简单点
int d[7];
d[0]=a[0];
for(int i=1;i<=7;i++){
d[i]=a[i]-a[i-1];
}
差分数组是干什么用的?
单点查询
让我们先看看它的规律,现在:
d a
d[0]=1 a[0]=1
d[1]=1 a[1]=2
d[2]=2 a[2]=4
d[3]=1 a[3]=5
d[4]=7 a[4]=12
d[5]=22 a[5]=34
d[6]=89 a[6]=123
d[7]=-120 a[7]=3
你会惊奇地发现,
a[0]=d[0];
a[1]=d[1]+d[0];
a[2]=d[2]+d[1]+d[0];
…
以此类推
这样就可以单点查询
区间修改
如果现在要修改a[0]-a[4],只需要把d[0]+1(所有的a都有d[0]的元素),然后把d[5]-1(a[5]及以后的数字都有d[5]的元素)
a[0]=d[0]
a[1]=d[1]+d[0]+1
a[2]=d[2]+d[1]+d[0]+1
a[3]=d[3]+…+d[0]+1
a[4]=d[4]+…+d[0]+1
a[5]=d[5]-1+…+d[0]+1
a[6]=d[6]+d[5]-1+…+d[0]+1
a[5]=d[7]+d[6]+d[5]-1+…+d[0]+1
差分数组的时间复杂度是O(2) 区间修改就变成了两个单点修改
O(n)变成O(2)了
缺点!
不得不说一下它的缺点,就是如果过多次查询,过少次修改,它的时间复杂度可能会比不用任何算法要高。写题目的时候要三思而后行。
如果还是一定要用的话,一定要与树状数组一起用
作者:johnwayne0317
来源:CSDN
原文:https://blog.csdn.net/johnwayne0317/article/details/84928568
版权声明:本文为博主原创文章,转载请附上博文链接!