最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 20210302 LeetCode 每日一题,冲!|刷题打卡

    正文概述 掘金(小诸不是小猪)   2021-03-02   570

    题目描述

    Leetcode 链接:304 二维区域和检索 - 矩阵不可变(medium)

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

    20210302 LeetCode 每日一题,冲!|刷题打卡

    上图子矩阵左上角 (row1, col1) = (2, 1) ,右下角(row2, col2) = (4, 3),该子矩形内元素的总和为 8

    示例:

    给定 matrix = [
      [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]
    ]
    
    sumRegion(2, 1, 4, 3) -> 8
    sumRegion(1, 1, 2, 2) -> 11
    sumRegion(1, 2, 2, 4) -> 12
    

    提示:

    • 你可以假设矩阵不可变。
    • 会多次调用 sumRegion 方法。
    • 你可以假设 row1 ≤ row2 且 col1 ≤ col2 。

    JavaScript 模板:

    /**
     * @param {number[][]} matrix
     */
    var NumMatrix = function(matrix) {
    
    };
    
    /** 
     * @param {number} row1 
     * @param {number} col1 
     * @param {number} row2 
     * @param {number} col2
     * @return {number}
     */
    NumMatrix.prototype.sumRegion = function(row1, col1, row2, col2) {
    
    };
    
    /**
     * Your NumMatrix object will be instantiated and called as such:
     * var obj = new NumMatrix(matrix)
     * var param_1 = obj.sumRegion(row1,col1,row2,col2)
     */
    

    思路分析

    有了昨天前缀和的经验,第一个思路就是将二维的数组中的每一行都转换成用于表示前缀和的数组:

    1. 初始化一个前缀和数组,初始化的时间复杂度为 O(mn),空间复杂度为 O(mn),m 为行数,n 为列数:
    var NumMatrix = function (matrix) {
      if (matrix == 0) { // 注意 matrix 为 [[]] 的情况!
        this.empty = true;
      }
      else {
        let x = matrix[0].length, y = matrix.length;
        this.preSumArray = []; // 建立前缀和数组
        for (let i = 0; i < y; i++) {
          let preSum = [0];
          for (let j = 0; j < x; j++) {
            preSum[j + 1] = preSum[j] + matrix[i][j];
          }
          this.preSumArray.push(preSum); // 建立并添加每一行的前缀和数组
        }
      }
    };
    
    1. 在调用 sumRange 方法时,我们遍历每一行,然后返回其中指定位置的前缀和之差即可,查询的时间复杂度为 O(m),m 为行数:
    NumMatrix.prototype.sumRegion = function (row1, col1, row2, col2) {
      if (this.empty) { // 若为空数组则不返回值
        return;
      }
      let sum = 0;
      for (let i = row1; i < row2 + 1; i++) { // 计算每行的前缀和之差
        sum += this.preSumArray[i][col2 + 1];
        sum -= this.preSumArray[i][col1];
      }
      return sum;
    };
    

    运气不错,一次过了:

    20210302 LeetCode 每日一题,冲!|刷题打卡

    优化一下

    对于这个问题,随着二维矩阵的加入,我们查询的时间就变成了 O(m) 而非之前的 O(1),这样的查询速度肯定不是最理想的。那么我们有什么办法来继续缩短查询时间呢?其实办法是有的,关键点还是在于初始化。

    在上面的方法中,我们初始化的前缀和只是当前这行的前缀和,所以说我们在查询时才需要遍历每一行。我们可以在建立前缀和的时候就直接建立一个基于每一行以及每一列而形成的二维前缀和,这样的话在查询时,就可以以 O(1) 的时间复杂度求解了。

    20210302 LeetCode 每日一题,冲!|刷题打卡

    想象一下我们要求出蓝色部分的和时,我们只需要求出四个角所对应的二维前缀和即,然后进行一下运算就行了,即紫色部分减去橙色和红色部分,最后再加上绿色部分即可:

    1. 建立二维前缀和数组,时间复杂度为 O(mn),空间复杂度为 O(mn),m 为行数,n 为列数:
    var NumMatrix = function (matrix) {
      if (matrix == 0) {
        this.empty = true;
      }
      else {
        let x = matrix[0].length, y = matrix.length;
        this.preSumArray = new Array(y + 1).fill(0).map(() => new Array(x + 1).fill(0));
        for (let i = 0; i < y; i++) {
          for (let j = 0; j < x; j++) {
            this.preSumArray[i + 1][j + 1] = matrix[i][j] +
              this.preSumArray[i][j + 1] +
              this.preSumArray[i + 1][j] -
              this.preSumArray[i][j];
          }
        }
      }
    };
    

    不过在查询时,时间复杂度就降为了 O(1):

    NumMatrix.prototype.sumRegion = function (row1, col1, row2, col2) {
      if (this.empty) {
        return;
      }
      return this.preSumArray[row1][col1] +
        this.preSumArray[row2 + 1][col2 + 1] -
        this.preSumArray[row2 + 1][col1] -
        this.preSumArray[row1][col2 + 1]
    };
    

    提交一下:

    20210302 LeetCode 每日一题,冲!|刷题打卡

    总结一下

    通过在初始化时建立二维前缀和而非单行的前缀和,我们成功的将查询的时间复杂度从 O(m) 降到了 O(1),从而得到的更为高效的解法。

    小伙伴们一起来用 JavaScript 刷算法吧:LeetCode-JavaScript


    起源地下载网 » 20210302 LeetCode 每日一题,冲!|刷题打卡

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元