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

  • 计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2) 。实现 NumMatrix 类:
  • NumMatrix(int[][] matrix) 给定整数矩阵 matrix 进行初始化
  • int sumRegion(int row1, int col1, int row2, int col2) 返回左上角 (row1, col1) 、右下角 (row2, col2) 的子矩阵的元素总和。

示例 1:

输入: 
// ["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 (蓝色矩形框的元素总和)

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 200
  • -10 ^ 5 <= matrix[i][j] <= 10 ^ 5
  • 0 <= row1 <= row2 < m
  • 0 <= col1 <= col2 < n
  • 最多调用 10 ^ 4 次 sumRegion 方法

注意:本题与LeetCode 304 题相同。

思路分析

本题可以采用前缀和的思路来解答。我们可以在初始化时,对每一行计算前缀和,然后检索时对二维区域的每一行计算子数组的和,然后对每一行的子数组计算总和。

具体实现来讲,就是初始化一个m行n + 1列的二维数组sums,其中m为矩阵的行数,n为矩阵的列数,sums[i]为matrix[i]的前缀和数组。将sums的列数设为n + 1的目的主要是方便计算每一行的子数组和,而不需要对col1 = 0做处理。具体代码如下:

/**
 * @param {number[][]} matrix
 */
var NumMatrix = function(matrix) {
    //行数
    const m =  matrix.length;
    if(m > 0){
        //列数
        const n = matrix[0].length;
        //初始化前缀和二维数组
        this.sums = [];
        //这里是为了初始化二维数组的每一项为0
        for(let i = 0;i < m;i++){
            this.sums[i] = [];
            for(let j = 0;j <= n;j++){
                this.sums[i][j] = 0;
            }
        }
        //计算sums[i]的前缀和
        for(let k = 0;k < m;k++){
            for(let l = 0;l < n;l++){
                this.sums[k][l + 1] = this.sums[k][l] + matrix[k][l];
            }
        }
    }
};

/** 
 * @param {number} row1 
 * @param {number} col1 
 * @param {number} row2 
 * @param {number} col2
 * @return {number}
 */
NumMatrix.prototype.sumRegion = function(row1, col1, row2, col2) {
    let sum = 0;
    for(let i = row1;i <= row2;i++){
        sum += this.sums[i][col2 + 1] - this.sums[i][col1];
    }
    return sum;
};

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

以上算法的时间复杂度和空间复杂度分析如下:

  • 时间复杂度O(n * m),其中m为矩阵的行数,n为矩阵的列数。
  • 空间复杂度O(n * m)。
Apple

Apple

Graduated in Computer Science and Engineering, but currently working with GNU/Linux infrastructure and in the spare time I'm an Open Source programmer (Python and C), a drawer and author in the YINGJUE Blog.


Comments