差分数组算法

举例


考虑数组 a = [ 1 , 3 , 3 , 5 , 8 ] a=[1,3,3,5,8] a=[1,3,3,5,8],对其中的相邻元素两两作差(右边减左边),得到数组 [ 2 , 0 , 2 , 3 ] [2,0,2,3] [2,0,2,3]。然后在开头补上 a [ 0 ] a[0] a[0],得到差分数组
d = [ 1 , 2 , 0 , 2 , 3 ] d=[1,2,0,2,3] d=[1,2,0,2,3]
这有什么用呢?如果从左到右累加 d d d 中的元素,我们就「还原」回了 a a a 数组 [ 1 , 3 , 3 , 5 , 8 ] [1,3,3,5,8] [1,3,3,5,8]。这类似求导与积分的概念。

这又有什么用呢?现在把连续子数组 a [ 1 ] , a [ 2 ] , a [ 3 ] a[1],a[2],a[3] a[1],a[2],a[3] 都加上 10 10 10,得到 a ′ = [ 1 , 13 , 13 , 15 , 8 ] a^{\prime}=[1,13,13,15,8] a=[1,13,13,15,8]。再次两两作差,并在开头补上 a ′ [ 0 ] a^′[0] a[0],得到差分数组
d ′ = [ 1 , 12 , 0 , 2 , − 7 ] d ^′=[1,12,0,2,−7] d=[1,12,0,2,7]
对比 d d d d ′ d^′ d,可以发现只有 d [ 1 ] d[1] d[1] d [ 4 ] d[4] d[4] 变化了,这意味着对 a a a 中连续子数组的操作,可以转变成对差分数组 d d d两个数的操作。

定义和性质


对于数组 a a a,定义其差分数组(difference array)为

d [ i ] = { a [ 0 ] , i = 0 a [ i ] − a [ i − 1 ] , i ≥ 1 d[i]=\left\{\begin{array}{ll} a[0], & i=0 \\ a[i]-a[i-1], & i \geq 1 \end{array}\right. d[i]={a[0],a[i]a[i1],i=0i1

性质 1:从左到右累加 d d d 中的元素,可以得到数组 a a a

性质 2:如下两个操作是等价的。

  • a a a 的子数组 a [ i ] , a [ i + 1 ] , ⋯ , a [ j ] a[i],a[i+1],⋯,a[j] a[i],a[i+1],,a[j] 都加上 x x x
  • d [ i ] d[i] d[i] 增加 x x x,把 d [ j + 1 ] d[j+1] d[j+1] 减少 x x x

利用性质 2,我们只需要 O ( 1 ) O(1) O(1) 的时间就可以完成对 a a a 的子数组的操作。最后利用性质 1 从差分数组复原出数组 a a a

注:也可以这样理解, d [ i ] d[i] d[i] 表示把下标 ≥ i ≥i i 的数都加上 d [ i ] d[i] d[i]

示例


1094.Car Pooling

参考资料:
https://leetcode.cn/problems/car-pooling/solutions/2550264/suan-fa-xiao-ke-tang-chai-fen-shu-zu-fu-9d4ra/

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值