二维前缀和(2D Prefix Sum)是一种用于处理二维数组的技巧,它用于计算矩阵中子矩阵的和。通过使用二维前缀和,我们可以在常数时间内计算出给定矩阵中任意子矩阵的和。
假设我们有一个二维矩阵 matrix 如下所示:
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
我们首先根据上述步骤计算出二维前缀和数组 prefixSum:
prefixSum = [
[1, 3, 6],
[5, 12, 21],
[12, 27, 45]
]
子矩阵的和是什么?
例如,考虑以下原始矩阵:
1 2 3 4
5 6 7 8
9 10 11 12
如果我们选择子矩阵的左上角坐标为 (1, 1)、右下角坐标为 (2, 3),那么子矩阵的和将是:
6 7 8
10 11 12
子矩阵的和 = 6 + 7 + 8 + 10 + 11 + 12 = 54。
回到原来的位置,我们可以使用二维前缀和来计算子矩阵的和。
subMatrixSum = prefixSum[2][2] - prefixSum[0][2] - prefixSum[2][0] + prefixSum[0][0]
= 45 - 6 - 12 + 1
= 28
prefixSum[2][2]:它包含了子矩阵中所有元素的和。
prefixSum[0][2]:第一行所有元素的和。
prefixSum[2][0]:第一列所有元素的和。
prefixSum[0][0]:因为prefixSum[0][2]、prefixSum[2][0]重复计算了第一个位置上的元素,所以要加上。
之后子矩阵的和结果为白色方格中的所有元素和:
二维前缀和的计算步骤如下:
假设我们有一个原始矩阵 matrix,它包含 m 行 n 列的元素。我们可以使用二维前缀和数组 prefixSum 来存储原始矩阵中子矩阵和的信息。
1、创建一个大小为 (m+1) × (n+1) 的二维数组 prefixSum,并将所有元素初始化为0。
2、计算每个位置的前缀和:对于位置 (i, j) 的元素,它的前缀和等于原始矩阵中该位置的元素值加上前一行和前一列的前缀和之和,再减去左上方的元素的前缀和。即:
prefixSum[i][j] = matrix[i][j] + prefixSum[i-1][j] + prefixSum[i][j-1] - prefixSum[i-1][j-1]
3、计算子矩阵的和:要计算子矩阵的和,我们可以利用前缀和数组。对于子矩阵的左上角坐标为 (row1, col1),右下角坐标为 (row2, col2),子矩阵的和可以通过以下公式计算:
subMatrixSum = prefixSum[row2][col2] - prefixSum[row1-1][col2] - prefixSum[row2][col1-1] + prefixSum[row1-1][col1-1]
其中,prefixSum[row2][col2] 表示右下角坐标处的前缀和,prefixSum[row1-1][col2] 和 prefixSum[row2][col1-1] 分别表示排除一部分多计算的区域的前缀和,prefixSum[row1-1][col1-1] 表示左上角坐标处的前缀和。
实现代码:
public class Main {
public static void main(String[] args) {
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int subMatrixSum = calculateSubMatrixSum(matrix, 1, 1, 2, 2);
System.out.println(subMatrixSum); // 输出: 28
}
public static int calculateSubMatrixSum(int[][] matrix, int row1, int col1, int row2, int col2) {
int rows = matrix.length;
int cols = matrix[0].length;
// 创建前缀和数组并初始化为0
int[][] prefixSum = new int[rows + 1][cols + 1];
// 计算前缀和
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= cols; j++) {
prefixSum[i][j] = prefixSum[i - 1][j] + prefixSum[i][j - 1] - prefixSum[i - 1][j - 1]
+ matrix[i - 1][j - 1];
}
}
// 计算子矩阵的和
int subMatrixSum = prefixSum[row2 + 1][col2 + 1] - prefixSum[row1][col2 + 1] - prefixSum[row2 + 1][col1]
+ prefixSum[row1][col1];
return subMatrixSum;
}
}