java leetcode之[动态规划 中等]542. 01 矩阵

题目的链接在这里:https://leetcode-cn.com/problems/01-matrix/


题目大意

给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。

两个相邻元素间的距离为 1 。


一、示意图

在这里插入图片描述

二、解题思路

动态规划BFS

动态规划

代码如下:

class Solution {
    public int[][] updateMatrix(int[][] mat) {
        //再输出一个矩阵  每一个格子是mat中对应元素到最近的0的距离
        //重点就是怎么更新呢  如果一个位置是1 那就去判断他的四周的距离再加上1是吧 那前提是他的四周都更新过了呀
        //所以就像我说的 需要先从右下到左上进行一次动态规划 然后再是左上到右下
        int[][] result=new int[mat.length][mat[0].length];
        //要对result进行初始值判断  初始值全是0
        int xLength=mat.length;
        int yLength=mat[0].length;

        //然后先从右下到左上吧
        for(int i=xLength-1;i>=0;i--){
            for(int j=yLength-1;j>=0;j--){
                //确实是需要初始化的
                result[i][j]=10000;
                //就是这个范围了
                if(mat[i][j]==0){
                    //说明都不需要判断
                    //这里就需要进行操作了
                    result[i][j]=0;
                    continue;
                }
                else{
                    /**
                     * 不然的话 就需要进行动态规划了
                     * 这样的 右下到左上的运行轨迹是 从最右下的 先往左移 然后再一直左移 然后直到到最前一个 然后到上一层的最右边这样 
                     * 所以原则上来说 他只能和当前的自己 不是和上一个做对比 而是需要和自己相邻的做对比 而和自己相邻的 并且以及被访问过的 只可能是 自己的右边 以及自己的下面 这些都可以进行访问的
                     * 如果是i等于 xLength-1 说明在最后一层 那只可能是在右边 而如果j在yLength-1 也就是说 他只可能在 下面 所以需要进行判断
                     * 判断方法就是 反向操作  既然不能等于这些 那就进行不等于这些的操作
                     */
                   if(i<xLength-1){
                       //这个就说明 他一定是可以和下边的这个进行判断的
                       result[i][j]=Math.min(result[i][j],result[i+1][j]+1);
                   }
                   if(j<yLength-1){
                       //那就是说明 他也一定是可以和他 右边这个进行判断的
                       result[i][j]=Math.min(result[i][j],result[i][j+1]+1);
                   }
         
                }
            }
        }
        
        //这样右下到左上就完成了 然后第二次动态规划就是 左上到右下
        for(int i=0;i<xLength;i++){
            for(int j=0;j<yLength;j++){
                //这个就不用初始化了 并且 这里移动方向就是从 左一直右移 然后到下一层的最左边
                if(mat[i][j]==0){
                    //感觉像是多余操作 
                    result[i][j]=0;
                }
                else{
                    /**
                     * 开始动态规划 一般来说 是可以和自己的左边 以及上边比的 但如果在第一行 就只能和左边比较 如果在第一列 就只能和自己的上边比较
                     */
                    if(i>0){
                        //说明不在第一行 可以和自己的上边比较了
                        result[i][j]=Math.min(result[i][j],result[i-1][j]+1);
                    }
                    if(j>0){
                        //说明不在第一列 可以和自己的左边进行比较了
                        result[i][j]=Math.min(result[i][j],result[i][j-1]+1);
                    }
                }
            }
        }
        return result;
}
}

在这里插入图片描述

bfs

代码如下:

class Solution {
       public int[][] updateMatrix(int[][] mat) {
      //用BFS试试看
        Queue<int[]> queue=new LinkedList<>();
        //然后把其中的所有0的都进队列中
        for(int i=0;i<mat.length;i++){
            for(int j=0;j<mat[0].length;j++){
                if(mat[i][j]==0){
                    queue.add(new int[]{i,j});
                }
            }
        }
        //然后是他的四个方位
        int[][] pos={{0,1},{0,-1},{1,0},{-1,0}};
        int[][] res=new int[mat.length][mat[0].length];
        int step=0;
        while (!queue.isEmpty()){
            //先把第一波等于0的放进去
            //也就是意味着 res默认值是0 而那些在第一波0边上的1 也全都是变成了距离为一 也就是从0开始扩散出去 每一次都进行扩散
            step++;
            int size=queue.size();
            for(int i=0;i<size;i++){
                //然后取出这几个
                int[] poll = queue.poll();
                //并进行更新
                for(int j=0;j<4;j++){
                    int newX=poll[0]+pos[j][0];
                    int nexY=poll[1]+pos[j][1];
                    //然后进行判断  需要是合法的 并且是等于1 的
                    if(newX>=0&&newX<mat.length&&nexY>=0&&nexY<mat[0].length&&mat[newX][nexY]==1){
                        //说明这一波1是距离对应的0 最近的一批 也就是第一步的这些
                        res[newX][nexY]=step;
                        //然后为了防止他们 再次被访问到 设置成0
                        mat[newX][nexY]=0;
                        //并把数值 放到队列当中
                        queue.add(new int[]{newX,nexY});
                    }
                }
                
            }
        }
        return res;
}
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值