LeetCode 304. 二维区域和检索 - 矩阵不可变

304. 二维区域和检索 - 矩阵不可变

 

【二维前缀和】借此题正好讲解一下二维前缀和的问题,在求前缀和的时候我们最好画个图

(1)这是要求前缀和的区域

LeetCode 304. 二维区域和检索 - 矩阵不可变_第1张图片

注意对( i, j )区域求前缀和之前,( i - 1, j ), ( i , j - 1 ), (i - 1, j - 1)这些区域是默认都已经求了前缀和的

(2)首先加上蓝色区域,也就是(i, j - 1)这部分

LeetCode 304. 二维区域和检索 - 矩阵不可变_第2张图片

(3)再加上橙色区域,也就是(i - 1, j)的部分,这时候我们发现重复加了一部分

LeetCode 304. 二维区域和检索 - 矩阵不可变_第3张图片

 (4)所以还要把重复加的部分剪去,也就是(i - 1, j - 1)这一部分

LeetCode 304. 二维区域和检索 - 矩阵不可变_第4张图片

最后不要忘记加上原数组的(i, j)

下面看一下如何计算指定区域的和,有了前缀之后就好办了,例如计算(x1, y1)到(x2, y2)区域的和

首先用(x2, y2) - (x1 - 1, y2) - (x2, y1 - 1)这样就减去了两个长条的绿色部分的面积,但是有个小绿色区域被减了两次,所以还要在加上一个(x1 -1, y1 - 1)的值

LeetCode 304. 二维区域和检索 - 矩阵不可变_第5张图片

 

class NumMatrix {

    int[][] pre;

    public NumMatrix(int[][] matrix) {
        int m = matrix.length, n = matrix[0].length;
        pre = new int[m + 1][n + 1];
        for(var i = 1; i <= m; i++){
            for(var j = 1; j <= n; j++){
                pre[i][j] = pre[i][j - 1] + pre[i - 1][j] - pre[i - 1][j - 1] + matrix[i - 1][j - 1];
            }
        }
    }
    
    public int sumRegion(int row1, int col1, int row2, int col2) {
        return pre[row2 + 1][col2 + 1] - pre[row1][col2 + 1] - pre[row2 + 1][col1] + pre[row1][col1];
    }
}

/**
 * Your NumMatrix object will be instantiated and called as such:
 * NumMatrix obj = new NumMatrix(matrix);
 * int param_1 = obj.sumRegion(row1,col1,row2,col2);
 */

 

 

你可能感兴趣的:(LeetCode,前缀和)