二维差分数组
1. 前置概念:二维数组与差分
- 二维数组:二维数组可以看作是一个矩阵,它有行和列。在编程中,通常使用嵌套列表来表示二维数组。例如,在 Python 中,
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]就是一个 3 行 3 列的二维数组。 - 差分:差分是一种与前缀和相对的概念。对于一维数组,差分是指相邻元素之间的差值。而二维差分数组是将差分的思想扩展到二维空间。
2. 二维差分数组的定义
设原二维数组为 a[i][j](其中 i 表示行索引,j 表示列索引),其对应的二维差分数组为 b[i][j]。二维差分数组 b[i][j] 满足以下关系:
b[1][1]=a[1][1]b[i][1]=a[i][1] - a[i - 1][1] (i > 1)b[1][j]=a[1][j] - a[1][j - 1] (j > 1)b[i][j]=a[i][j]-a[i - 1][j]-a[i][j - 1]+a[i - 1][j - 1] (i > 1, j > 1)
简单来说,二维差分数组 b[i][j] 记录的是原数组 a 中以 (i, j) 为右下角,(1, 1) 为左上角的子矩阵与相邻子矩阵之间的“变化量”。
3. 二维差分数组的作用
二维差分数组主要用于高效地处理二维数组的区间更新问题。如果要对原二维数组中一个子矩阵的所有元素进行相同的增量操作,使用原数组直接更新的时间复杂度是 O(n∗m)O(n * m)O(n∗m)(其中 n 和 m 分别是子矩阵的行数和列数),而使用二维差分数组可以将时间复杂度降低到 O(1)O(1)O(1)。
4. 二维差分数组的操作
4.1 构造二维差分数组
def build_difference_array(original):rows = len(original)cols = len(original[0])diff = [[0] * (cols + 1) for _ in range(rows + 1)]for i in range(1, rows + 1):for j in range(1, cols + 1):diff[i][j] = original[i - 1][j - 1] - original[i - 1][j - 2] - original[i - 2][j - 1] + original[i - 2][j - 2]return diff
4.2 区间更新操作
假设要对原数组中以 (x1, y1) 为左上角,(x2, y2) 为右下角的子矩阵的所有元素加上一个值 val,只需要对差分数组进行以下操作:
def update_difference_array(diff, x1, y1, x2, y2, val):diff[x1][y1] += valdiff[x1][y2 + 1] -= valdiff[x2 + 1][y1] -= valdiff[x2 + 1][y2 + 1] += val
4.3 从差分数组还原原数组
def restore_original_array(diff):rows = len(diff)cols = len(diff[0])original = [[0] * (cols - 1) for _ in range(rows - 1)]for i in range(1, rows):for j in range(1, cols):original[i - 1][j - 1] = original[i - 1][j - 2] + original[i - 2][j - 1] - original[i - 2][j - 2] + diff[i][j]return original
5. 示例代码
# 原二维数组
original = [[1, 2, 3],[4, 5, 6],[7, 8, 9]
]# 构造差分数组
diff = build_difference_array(original)# 对原数组中以 (1, 1) 为左上角,(2, 2) 为右下角的子矩阵的所有元素加 2
update_difference_array(diff, 1, 1, 2, 2, 2)# 从差分数组还原原数组
new_original = restore_original_array(diff)print(new_original)
6. 复杂度分析
- 时间复杂度:
- 构造差分数组:O(n∗m)O(n * m)O(n∗m),其中
n和m分别是原数组的行数和列数。 - 区间更新操作:O(1)O(1)O(1)。
- 从差分数组还原原数组:O(n∗m)O(n * m)O(n∗m)。
- 构造差分数组:O(n∗m)O(n * m)O(n∗m),其中
- 空间复杂度:O(n∗m)O(n * m)O(n∗m),主要用于存储差分数组。
