void prefix(int n, int m) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
preSum[i][j] = preSum[i - 1][j] + preSum[i][j - 1]
- preSum[i - 1][j - 1] + arr[i][j];
}
}
}
以上为得到presum数组。
其原理如下:
通过这个计算前缀和数组的方式,可以计算任意子矩阵的元素和。
假设有一个二维数组 arr 如下:
1 2 3
4 5 6
7 8 9
创建一个新的数组,初始化为0:
0 0 0
0 0 0
0 0 0
计算每个位置的前缀和:
1 3 6
5 12 21
12 27 45
这个 preSum 数组的含义是,preSum[i][j] 记录了从 (0,0) 到 (i,j) 的子矩阵的元素之和。
例如,preSum[2][2] 表示了从 (0,0) 到 (2,2) 的子矩阵的元素之和为 45。
通过这个 preSum 数组,可以在 O(1) 的时间复杂度内计算任意子矩阵的元素之和。例如,计算子矩阵 [(1,1), (2,2)] 的元素之和:
sum=preSum[2][2]-preSum[2][0]-preSum[0][2]+preSum[0][0]
=45-6-12+1
=28
这样就得到了子矩阵 [(1,1), (2,2)] 的元素之和为 28
一般代码(公式)如下:
int getSum(int x1, int x2, int y1, int y2) {
return preSum[x2][y2] - preSum[x1 - 1][y2] - preSum[x2][y1 - 1]
+ preSum[x1 - 1][y1 - 1];
}
例如
a b c
d e f
g h i
矩阵 e f
h i
的元素和为
presum(i)-presum(g)-presum(c)+presum(a)