对于一个数组
nums = [1,5,2,6,3,-1],
它的前缀和数组(前n项和)为
f = [1,6,8,14,17,16],
它的差分数组 (d[ i ] = nums[ i ]-nums[ i - 1 ])
d = [1,4,-3,4,-3,-4],而差分数组d的前缀和数组就是nums
而当数组区间 [ l ,r ] 进行加减操作
nums[ l , r ]+v
时,无需对每一个数字进行独立的操作,只需对数组的差分左右侧进行操作,使
d[ l ] += v ,d[ r+1 ] -= v,
即可通过该差分的前缀和获得操作后的数组
int[] nums = {1,5,2,6,3,-1};//基本的一个nums
int[] f = {1,6,8,14,17,16};//nums的前n项和,即前缀和
int[] d = {1,4,-2,4,-3,-4};//nums的差分,即nums[i]-nums[i-1]
int[] df = new int[6];//nums的差分的前缀和
nums = {nums[0],nums[1],nums[2],nums[3],nums[4],nums[5]};//nums的每一项都是nums[i]
f = {nums[0],f[1],f[2],f[3],f[4],f[5]};//差分的每一项都是f[i]
f = {nums[0],//f[i]即是前n项和
nums[0]+nums[1],
nums[0]+nums[1]+nums[2],
nums[0]+nums[1]+nums[2]+nums[3],
nums[0]+nums[1]+nums[2]+nums[3]+nums[4],
nums[0]+nums[1]+nums[2]+nums[3]+nums[4]+nums[5]};
d = {nums[0],//差分则是nums[i]-nums[i-1],i=1时取nums的第一项
nums[1]-nums[0],
nums[2]-nums[1],
nums[3]-nums[2],
nums[4]-nums[3],
nums[5]-nums[4]}
df = {nums[0],//再计算差分的前n项和
nums[1]-nums[0]+nums[0],//可以消去左右的nums[0]
nums[1]+nums[2]-nums[1],//这里左右的nums[0]已经被消去了,nums[1]也会被消去
nums[2]+nums[3]-nums[2],
nums[3]+nums[4]-nums[3],
nums[4]+nums[5]-nums[4]
}
df = {nums[0],nums[1],nums[2],nums[3],nums[4],nums[5]//最终得到的又是nums
}
nums = {1,5,2,6,3,-1};
nums[2,4]+5
nums[1,2]-4
nums[3,5]+1
->
nums = {1,1,3,12,9,0}//执行所有操作之后的nums
d = {1,4,-2,4,-3,-4}
//关于区间[l,r]内所有数执行加减操作可视作nums[l]+v,nums[r+1]-v
d[2,4]+5 -> d[2]+5,d[5]-5//d[l]+v,d[r+1]-v
d[1,2]-4 -> d[1]-4,d[3]+4
d[3,5]+1 -> d[3]+1,d[6]+1//这里d[6]不存在,取0
->
{1,0,2,9,-3,-9}//执行操作后的差分数组
df = {1,1,3,12,9,0}//差分数组的前缀和,执行正常流程的原数组一致
原理解释:
由上面的解释可知,差分数组的前n项和就是原数组,当区间[ l , r ]进行减操作时,只要将 l 减去v,那么下标为 l 之后的前n项和都会减少v,并且 l 之前的前n项和都保持正常,但要保证 r 后面的数字不受影响就应当再补偿减去的v,所以会在 r+1 处加上v,如此一来 r 之后的前n项和又会正常得出,最后取差分的前缀和即是执行操作后的数组。