【Leetcode刷题】NO.2

123 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

1.题目

304. 二维区域和检索 - 矩阵不可变 给定一个二维矩阵 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:

image.png

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

二、思路分析:

这道题最简单的方法就是暴力求解,即利用for循环求解问题,但是由于时间复杂度过高所以需要采用别的方法,类似这种求和问题我们一般会想到前缀和框架求解问题,在二维数据利用前缀和的思路时,我们需要建立二维的前缀和数组用来存储数据,我们首先看到测试用例,需要求出红色方框的元素和,我们可以看到结果可以用这个大方框的元素和减去蓝色方框和绿色方框的元素和,在加上紫色方框的元素和就能够得到结果,所以我们的前缀和每一格子的值就可以存储从这个格子到起始点的元素和求解即可.

特别注意,我们要注意边界问题,所以我们需要扩大二维数组进行存储前缀和

image.png

三、代码:

/**
 * @param {number[][]} matrix
 */
var NumMatrix = function(matrix) {
    let m = matrix.length
    let n = matrix[0].length
    if(m == 0 || n == 0) return 
    let preSum = new Array(m+1).fill(0).map(v => new Array(n+1).fill(0))
    for(let i=1 ; i<=m ; i++){
        for(let j=1 ; j<=n ; j++){
            preSum[i][j] = preSum[i][j-1] + preSum[i-1][j] -preSum[i-1][j-1] + matrix[i-1][j-1]
        }
    }
    this.preSum = preSum
};

/** 
 * @param {number} row1 
 * @param {number} col1 
 * @param {number} row2 
 * @param {number} col2
 * @return {number}
 */
NumMatrix.prototype.sumRegion = function(row1, col1, row2, col2) {
    return this.preSum[row2+1][col2+1] - this.preSum[row1][col2+1] - this.preSum[row2+1][col1] + this.preSum[row1][col1]
};

时间复杂度:O(1)

四、总结:

每次遇到此类求解元素和问题的时候,我们都需要想到前缀和框架的思想,用框架去求解问题往往能够举一反三,但是这种问题通常要仔细考虑边界问题,索引该怎么取等等这些细节,这是我刷前缀和问题的第二题,希望再接再厉0.0