讲解-前缀和
先给出一个示例,在给出计算二维矩阵二维前缀和的公式。
要求f(2,2)前缀和,需要求f(1,2)、f(2,1)以及f(1,1)的前缀和,显然f(1,2)和f(2,1)会加上两次f(1,1),所以需要减去一次f(1,1)最后加上矩阵martix[2][2]的值。
求二维矩阵前缀和代码如下。前两个for循环是将左侧和上侧进行初始化。
public int[][] getPreSum(int[][] matrix) {
int[][] preSum;
int m = matrix.length;
int n = matrix[0].length;
preSum = new int[m][n];
for(int i = 0;i < m;i++){
if(i == 0){
preSum[i][0] = matrix[i][0];
}else{
preSum[i][0] = preSum[i - 1][0] + matrix[i][0];
}
}
for(int j = 0;j < n;j++){
if(j == 0){
preSum[0][j] = matrix[0][j];
}else{
preSum[0][j] = preSum[0][j - 1] + matrix[0][j];
}
}
for(int i = 1;i < m;i++){
for(int j = 1; j < n;j++){
preSum[i][j] = preSum[i - 1][j] + preSum[i][j - 1] - preSum[i - 1][j - 1] + matrix[i][j];
}
}
return preSum;
}
讲解-区域和
有了前缀和,就很容易求解矩阵某个区域的和。求解区域和公式如下。显然要求和区域和为r(1,1,2,2),需要知道f(2,2)、f(2,0)、f(0,2)以及f(0,0),显然f(2,2)剪去f(0,2)和f(2,0)会多减去一次f(0,0),需要再加上一次f(0,0)。
求区域和代码如下,主要注意的是,当row1-1和col1-1小于零时需要考虑特殊,如果为下标小于零,则将公式中的对应下标小于零的项去除即可。
public int sumRegion(int[][] preSum, int row1, int col1, int row2, int col2) {
int res = 0;
if(row1 - 1 < 0 && col1 - 1 < 0){
res = preSum[row2][col2];
}else if(col1 - 1 < 0){
res = preSum[row2][col2] - preSum[row1 - 1][col2];
}else if(row1 - 1 < 0){
res = preSum[row2][col2] - preSum[row2][col1 - 1];
}else{
res = preSum[row2][col2] - preSum[row2][col1 - 1] - preSum[row1 - 1][col2] + preSum[row1 - 1][col1 - 1];
}
return res;
}