算法33.0

1314. 矩阵区域和 - 力扣(LeetCode)


自己的理解:

算题的时候 计算二维数组的和的时候 第一反应是按照自己的方式 并没有联想到之前学习过二维前缀和的内容 必要且及时的复习

如何快速的得出二维数组的前缀和公式:

提示:两个图片能否勾起算法27.0 里面的解析

分为如何求 dp i j 以及如何使用前缀和数组 这两个图片一个对应一个

dp\[\]\[\]是要注意面积的拆分 使用是要注意明确好区间之后 大面积减去小面积

如何计算answer某一个位置的数?

首先这里的k并不是固定的等于1 所以这个绿框框的范围是根据k的大小而改变的

如何确定这个范围呢? 受到使用二维前缀和数组那里的启示 其实是要确定左上角和右下角的坐标 确定好了之后 这个范围就确定了 再把这个范围套到mat(arr)上进行计算

注意数组越界异常 因为这个往mat数组上套的时候 有时候一部分是在外面的 外面的这部分元素不需要也获取不到 还会造成数组越界异常 就像下面的情况(k=1)

这个时候要怎么解决?

对于左上角方块 我们需要注意的是补药小于0 而对于右下角方块 我们需要注意的是补药超了mat数组本身

我们可以用函数来解决这个问题 取值

小的不可能小过0 大的不可能大过m-1(边界)

下标的映射关系:?

在之前学习二维前缀和模板的时候 为了避免边界情况的麻烦 我们是默认了dp数组下标从1开始

但是这道题的数组下标是从0开始的 这个时候要怎么解决? 画出来好理解一些:

如果这里有点迷糊的话 从算法27.0推导出来的公式入手

D = dp x2 y2 - dp x1-1 y2 - dp x2 y1-1 如果x1取0的话 是负1 这里需要处理边界情况

之前的话 我们的arr数组从1开始 我们的dp也是从1开始 (但是现在dp是从0开始 扩充了)

填写dp表(1,1)的时候,我们需要在mat表里面找的是(0,0)

同理 使用dp表的时候 ans也是从0开始计数的 填写ans(0,0)的时候 dp表需要统一加1

.这样太麻烦了 当用到dpi的时候统一加一减一的

更方便的是 在求下标的时候 直接加1

求answer边界的时候 直接在answer上面加1 对应到dp表里面

解释:想象一下 你有一个正常的世界 和 一个带缓冲区的世界

正常的世界是原矩阵 房子编号从0 开始 0 1 2 3 4 ...

带缓冲的世界是dp表 房子编号从0开始 0(缓冲区) 1 2 3 4 ...

之前我们为了避免边界 规定了0号房子是空的缓冲区 从1号开始才对应正常世界的房子

这样设定之后

在正常的世界中 你想要从2号房子到4号房子的朋友:

正常世界:2号到4号 带缓冲的世界:需要找3号到5号(因为1号对应正常世界的0号)

与其每次都在脑子里面转换:正常世界的2号房子对应缓冲世界的3号 正常世界4号对应缓冲5号

不如统一规则:只要从正常的世界去缓冲世界 所有地址自动+1

放到代码里表现就是:

int x1 = Math.max(0,i-k)+1 ,y1=Math.max(0,j-k)+1;

int x2 = Math.min(m-1,i+k)+1 ,y2=Math.min(n-1,j+k)+1;

这样就会简化很多步骤


细节:

审题:这道题目审题比较不容易 其实就是要把握住关键概念 少一点想法多一点现实迭代

本题:answer二维数组和mat二维数组同等规模

这个是审题的关键 : i-k<= r <= i+k j-k <= c <= j+k 带入数字之后-1<= r <= 1 这个 表示的是在mat数组上从-1 到 1 的位置


别人的讲解:

下面是题目、效果图和代码:
java 复制代码
class Solution 
{
    public int[][] matrixBlockSum(int[][] mat, int k) 
    {
        
     //先求一下原矩阵的规模
     int m = mat.length , n = mat[0].length;

     //1.预处理一个前缀和矩阵
     int[][] dp = new int[m+1][n+1];
     for(int i = 1; i<= m; i++ ){
       for(int j = 1;j<=n ; j++)
        dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+mat[i-1][j-1];}

    //2.使用前缀和矩阵
    int[][] ret = new int[m][n]; //同等大小就可以
    for(int i = 0; i<m; i++ )
      for(int j = 0;j<n ; j++)
      {
        int x1 = Math.max(0,i-k)+1,y1=Math.max(0,j-k)+1;
        int x2 = Math.min(m-1,i+k)+1,y2=Math.min(n-1,j+k)+1;
        ret[i][j]=dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1];
      }
    return ret; 
    }
}

//xiyu251113&1#4*8
相关推荐
青山木6 分钟前
Hot 100 --- 最小栈
java·数据结构·算法·leetcode
疯狂打码的少年10 分钟前
【数据结构】栈的应用:表达式求值(后缀表达式)
java·数据结构·笔记·算法
HiDev_20 分钟前
【非标自动化】plc执行顺序问题、扫描周期问题
深度学习·算法·机器学习
高洁011 小时前
工信部教考中心证书-人工智能系列本系列
人工智能·python·深度学习·算法
陈王卜1 小时前
Reduce 算子优化笔记
算法
wabs6661 小时前
关于图论【最短路径之Bellman_ford 算法(判断负权回路)|卡码网95.城市间货物运输II的思考】
数据结构·算法·图论·bellman_ford算法·卡码网·判断负权回路
YouonlyliveonceC1 小时前
《大话数据结构》第4章实战:中缀表达式转后缀 + 后缀表达式求值(完整可运行实现)
算法
phoenix@Capricornus2 小时前
从统计决策到贝叶斯估计
人工智能·算法·机器学习
AICDragon2 小时前
1.8%就够了:K3的896个MoE专家,为什么激活率这么低反而是好事?
人工智能·算法
VALENIAN瓦伦尼安教学设备2 小时前
ASHOOTER激光对中仪如何通过颜色确定调整是否合适
数据库·嵌入式硬件·算法