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

807 阅读1分钟

算法记录

LeetCode 题目:

  给定一个二维矩阵 matrix,以下类型的多个请求:

  计算其子矩形范围内元素的总和,该子矩阵的左上角为(row1, col1) ,右下角为 (row2, col2) 。

  • NumMatrix() 给定整数矩阵 matrix 进行初始化
  • int sumRegion() 返回左上角 (row1, col1) 、右下角 (row2, col2) 所描述的子矩阵的元素总和 。

说明

一、题目

输入: 
["NumMatrix","sumRegion","sumRegion","sumRegion"]
[[[[3,0,1,4,2],[5,6,3,2,1],[1,2,0,1,5],[4,1,0,1,7],[1,0,3,0,5]]],[2,1,4,3],[1,1,2,2],[1,2,2,4]]
输出: 
[null, 8, 11, 12]

解释:
NumMatrix numMatrix = new NumMatrix([[3,0,1,4,2],[5,6,3,2,1],[1,2,0,1,5],[4,1,0,1,7],[1,0,3,0,5]]);
numMatrix.sumRegion(2, 1, 4, 3); // return 8 (红色矩形框的元素总和)
numMatrix.sumRegion(1, 1, 2, 2); // return 11 (绿色矩形框的元素总和)
numMatrix.sumRegion(1, 2, 2, 4); // return 12 (蓝色矩形框的元素总和)

二、分析

  • 题目不难,就是一个前缀和的二维应用,但是需要注意条件的划分,因为在计算的过程中会出现多计算的现象,需要进行规避。
  • 不画图不好解释,直接看代码可能还好理解一点。
class NumMatrix {
    private int[][] sums;
    private Integer m;
    private Integer n;
    public NumMatrix(int[][] matrix) {
        sums = matrix;
        m = matrix.length - 1;
        n = matrix[0].length - 1;
        for(int i = 0; i <= m; i++) {
            for(int j = 0; j <= n; j++) {
                if(i - 1 >= 0) sums[i][j] += sums[i - 1][j];
                if(j - 1 >= 0) sums[i][j] += sums[i][j - 1];
                if(i - 1 >= 0 && j - 1 >= 0) {
                    sums[i][j] -= sums[i - 1][j - 1];
                }
            }
        }
    }
    
    public int sumRegion(int row1, int col1, int row2, int col2) {
        int ret = sums[row2][col2];
        if(row1 - 1 >= 0) ret -= sums[row1 - 1][col2];
        if(col1 - 1 >= 0) ret -= sums[row2][col1 - 1];
        if(col1 - 1 >= 0 && row1 - 1 >= 0) ret += sums[row1 - 1][col1 - 1];
        return ret;
    }
}

总结

前缀和的二维应用。