分享|【算法小课堂】差分数组(Python/Java/C++/Go/JS)
28283
2023.08.21
2024.11.04
发布于 未知归属地

举例

考虑数组 ,对其中的相邻元素两两作差(右边减左边),得到数组 。然后在开头补上 ,得到差分数组

这有什么用呢?如果从左到右累加 中的元素,我们就「还原」回了 数组

这又有什么用呢?现在把连续子数组 都加上 ,得到 。再次两两作差,并在开头补上 ,得到差分数组

对比 ,你会发现,对 中连续子数组的操作,可以转变成对差分数组 两个数的操作。

定义和性质

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

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

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

  • 区间操作:把 的子数组 都加上
  • 单点操作:把 增加 ,把 减少 。特别地,如果 ,则只需把 增加 。( 为数组 的长度。)

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

代码模板

Python3
Java
C++
Go
JavaScript
# 你有一个长为 n 的数组 a,一开始所有元素均为 0。
# 给定一些区间操作,其中 queries[i] = [left, right, x],
# 你需要把子数组 a[left], a[left+1], ... a[right] 都加上 x。
# 返回所有操作执行完后的数组 a。
def solve(n: int, queries: List[List[int]]) -> List[int]:
    diff = [0] * n  # 差分数组
    for left, right, x in queries:
        diff[left] += x
        if right + 1 < n:
            diff[right + 1] -= x
    for i in range(1, n):
        diff[i] += diff[i - 1]  # 直接在差分数组上复原数组 a
    return diff

练习

分类题单

如何科学刷题?

  1. 滑动窗口与双指针(定长/不定长/单序列/双序列/三指针)
  2. 二分算法(二分答案/最小化最大值/最大化最小值/第K小)
  3. 单调栈(基础/矩形面积/贡献法/最小字典序)
  4. 网格图(DFS/BFS/综合应用)
  5. 位运算(基础/性质/拆位/试填/恒等式/思维)
  6. 图论算法(DFS/BFS/拓扑排序/最短路/最小生成树/二分图/基环树/欧拉路径)
  7. 动态规划(入门/背包/状态机/划分/区间/状压/数位/数据结构优化/树形/博弈/概率期望)
  8. 常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树)
  9. 数学算法(数论/组合/概率期望/博弈/计算几何/随机算法)
  10. 贪心与思维(基本贪心策略/反悔/区间/字典序/数学/思维/脑筋急转弯/构造)
  11. 链表、二叉树与一般树(前后指针/快慢指针/DFS/BFS/直径/LCA)
  12. 字符串(KMP/Z函数/Manacher/字符串哈希/AC自动机/后缀数组/子序列自动机)

我的题解精选(已分类)

欢迎关注 B站@灵茶山艾府

评论 (19)