Leetcode304.二维区域和检索——动态规划之矩阵前缀和

文章目录

引入

接上文Leetcode10.正则表达式匹配——动态规划之一个模型三个特征。在第17次双周赛的时候,我遇到这么一道题1314. 矩阵区域和

不过在此,我们先讨论该题的解法的经典题型

304.二维区域和检索 - 矩阵不可变
给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2)。
在这里插入图片描述
上图子矩阵左上角 (row1, col1) = (2, 1) ,右下角(row2, col2) = (4, 3),该子矩形内元素的总和为 8。
注:会多次调用区域求和方法。

拿到该题的时候,看到会多次调用区域求和方法时,就明白不能简单的每次计算区域每一行每一列的数值的和,必然是要保存其中间结果。

考虑到1310. 子数组异或查询,或者子数组求和的题目,我们一目了然,这道题应该用动态规划。

Leetcode题解

那么怎么去求动态规划方程呢?
首先,我们规定dp[i][j]表示区域(0,0)(i-1,j-1)的和,dp[1][1]就是(0,0)上点的值,dp[1][2]就是(0,0)加上(0,1)的值,以此类推。

为什么要这样规定呢?而不用dp[0][0]去表示(0,0)的值呢?
因为考虑到for循环是从0开始的,动态规划方程是根据前一个状态来计算的,所以,会导致数组越下界的情况发生。自然的,我们就想到初始化dp数组的时候,将其行列多增加1。

在规定了dp数组的定义后,就可以求解dp方程了。
在这里插入图片描述
我们要求解矩阵AD的和,我们手中的dp又是从O点开始计算的,我们唯一能拿到的只有OG、OE、OF、OD四个矩阵的值,自然的就可以得出:
A D = O D − O E − O F + O G AD=OD-OE-OF+OG AD=ODOEOF+OG
换成dp数组来表示,就是AD=dp[row2+1][col2+1]-dp[row2+1][col1]-dp[row1][col2+1]-dp[row1][col1]

结果表示出来了,但是dp数组怎么求还没说呢。
我们可以顺着刚才的思路,把求一个新的dp[i+1][j+1]看成这样:
矩阵AD就相当于新加入的点(i,j),没错就是把新加入的点看成一个矩阵,那么求解新的OD,就相当于:
O D = A D + O E + O F − O G OD=AD+OE+OF-OG OD=AD+OE+OFOG
换成dp数组来表示,dp[i+1][j+1]=matrix[i][j]+dp[i+1][j]+dp[i][j+1]-dp[i][j]

所以,我们的代码也就出来了:

class NumMatrix {
    int[][] dp;
    public NumMatrix(int[][] matrix) {
        if (matrix.length == 0 || matrix[0].length == 0) return;
        int row=matrix.length;
        int col=matrix[0].length;
        dp=new int[row+1][col+1];
        for(int i=0;i<row;i++){
            for(int j=0;j<col;j++){
                dp[i+1][j+1]=dp[i][j+1]+dp[i+1][j]+matrix[i][j]-dp[i][j];
            }
        }
    }
    
    public int sumRegion(int row1, int col1, int row2, int col2) {
        return dp[row2 + 1][col2 + 1] - dp[row1][col2 + 1] - dp[row2 + 1][col1] + dp[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);
 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值