数据结构 - 差分数组 Difference Array
在算法问题中,如何高效处理数组区间的修改操作是一个常见且重要的话题。比如:
- 需要在一个数组的多个区间上进行加减操作,最终输出结果;
- 频繁调整数组部分区间的值,但需要快速恢复整体状态;
- 处理二维平面或更高维数据的区域更新问题。
通常,我们可以使用暴力遍历的方法,但当数组规模较大、操作次数较多时,暴力方法的效率会迅速成为瓶颈。这时,我们就需要一种能够在常数时间内完成区间修改的高效工具——差分数组。
差分数组是一种借助“记录变化”而非直接修改原数组的巧妙方法。通过它,我们不仅可以快速处理区间修改,还可以在多次操作后迅速恢复最终的数组状态。本文将从基础概念出发,带你深入了解差分数组的工作原理、代码实现及其应用场景。
1. 什么是差分数组?
给定一个数组 \(a\),我们可以通过一个差分数组 \(diff\) 来表示 \(a\) 的变化:
- 定义 \(diff[i] = a[i] - a[i-1]\),(假设\(diff[0] = a[0]\));
- 由此,我们可以反推原数组:\(a[i] = a[i-1] + diff[i]\)。
2. 差分数组的基本操作
2.1 区间加值操作
假设我们希望再数组 \(a\) 的区间 \([l,r]\) 中所有元素都加上一个值 \(v\),差分数组的做法是:
diff[l] += v;
diff[r+1] -= v;
通过这样的操作,区间 \([l, r]\) 中的每个元素都会加上 \(v\)。因为
\[\begin{align*}
a[x] = a[x-1]+ diff[x] = a[l-1] + \sum_{l \leq i \leq x} diff[i], \quad (l \leq x \leq r).
\end{align*}
\]
在还原数组时,区间 \([l, r]\) 中的每个元素都会加上 \(diff[l]\),因此每个元素都会加上值 \(v\);而下标大于 $r $ 的元素不希望加上值 \(v\),因此令 \(diff[r+1]\) 自减即可。
2.2 数组还原操作
在完成多次区间操作后,我们通过前缀和的方式还原原始数组:
a[0] = diff[0];
a[i] = a[i-1] + diff[i];
3. 差分数组的复杂度分析
- 时间复杂度:\(O(n+q)\),其中 \(n\) 是数组长度,\(q\) 是区间修改的操作次数。
- 空间复杂度:\(O(n)\)

浙公网安备 33010602011771号