力扣解题思路:542. 01 矩阵 纠错记录

542. 01 矩阵

思路:在这里插入图片描述
先说我的思路,我想的是BFS+记忆数组,但是逻辑上出了点问题,先看我的错误代码:

private int[][] vector = new int[][]{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public int[][] updateMatrix(int[][] matrix) {
    if(matrix.length == 0) return new int[][]{};
    int[][] visited = new int[matrix.length][matrix[0].length];
    int[][] res = new int[matrix.length][matrix[0].length];
    for(int i=0;i<matrix.length;i++){
        for(int j=0;j<matrix[0].length;j++){
            if(matrix[i][j] == 1){
                bfs(matrix,i,j,visited,res);
            }
        }
    }
    return res;
}
public void bfs(int[][] matrix,int i,int j,int[][] visited,int[][] res){
    //if(visited[i][j] != 0) return visited[i][j];
    Queue<int[]> queue = new LinkedList<>();
    queue.add(new int[]{i,j});
    int level = 0;
    while(!queue.isEmpty()){
        level++;
        int size = queue.size();
        for(int p=0;p<size;p++){
            int[] s = queue.poll();
            int min = Integer.MAX_VALUE;
            for (int[] v : vector) {
                int r = s[0] + v[0], c = s[1] + v[1];
                if(r < 0 || r >= matrix.length
                        || c < 0 || c >= matrix[0].length) continue;
                if(visited[r][c] != 0){
                    min = Math.min(min,level + visited[r][c]);
                    //visited[i][j] = res[i][j];
                    //return;
                }
                if (matrix[r][c] == 0) {
                    min = Math.min(min,level);
                    //visited[i][j] = level;
                    //return;
                    
                }
                if(min == Integer.MAX_VALUE){
                    queue.add(new int[]{r, c});
                }else{
                    res[i][j] = min;
                    visited[i][j] = min;
                    return;
            }
        }
    }
}
输入:
[[0,0,0],[0,1,0],[1,1,1]]
输出:
[[0,0,0],[0,1,0],[1,2,3]]
预期结果:
[[0,0,0],[0,1,0],[1,2,1]]

我的代码看着就挺笨的。。。从测试用例就可以看出,我这个visited数组完全就是鸡肋,不如不要,因为我把这题当作最短路径在计算,其中level + visited[r][c]并不是最短的!要求最短的必须老老实实遍历直到遇到0,所以得去掉visited数组,也就是纯bfs那显然会超时。

所以,需要换个思路,如果我们从0开始遍历呢?那样岂不是能在每次BFS一圈的同时更新多个1的位置?于是,我写成了这个鬼样子:

public int[][] updateMatrix(int[][] matrix) {
    int m = matrix.length;
    if(m < 1) return matrix;
    int n = matrix[0].length;
    Queue<int[]> q = new LinkedList<>();
    for(int i = 0; i < m; ++i) {
        for(int j = 0; j < n; ++j) {
            if(matrix[i][j] == 1)
                matrix[i][j] = Integer.MAX_VALUE;
            else 
                q.offer(new int[]{i, j});
        }
    }
    int[][] dirs = {{-1,0}, {0,-1}, {1,0}, {0,1}};
    int level = 0;
    while(!q.isEmpty()) {
        int size = q.size();
        //System.out.println(size);
        level++;
        for(int i=0;i<size;i++){
            int[] node = q.poll();
            for(int[] dir : dirs) {
                int x = node[0]+dir[0];
                int y = node[1]+dir[1];
                if(x < 0 || x >= m || y < 0 || y >= n) continue;
                if(matrix[x][y] > 0) matrix[x][y] = Math.min(matrix[x][y],level); 
                q.offer(new int[]{x, y});
            }
        }
        
    }
    return matrix;
}

连终止条件都达不到,跳不出这个while循环,所以要再加个条件避免重复加入已经遍历过的节点:

public int[][] updateMatrix(int[][] matrix) {
    int m = matrix.length;
    if(m < 1) return matrix;
    int n = matrix[0].length;
    Queue<int[]> q = new LinkedList<>();
    for(int i = 0; i < m; ++i) {
        for(int j = 0; j < n; ++j) {
            if(matrix[i][j] == 1)
                matrix[i][j] = Integer.MAX_VALUE;
            else 
                q.offer(new int[]{i, j});
        }
    }
    int[][] dirs = {{-1,0}, {0,-1}, {1,0}, {0,1}};
    int level = 0;
    while(!q.isEmpty()) {
        int size = q.size();
        //System.out.println(size);
        level++;
        for(int i=0;i<size;i++){
            int[] node = q.poll();
            for(int[] dir : dirs) {
                int x = node[0]+dir[0];
                int y = node[1]+dir[1];
                if(x < 0 || x >= m || y < 0 || y >= n || matrix[x][y] <= level) continue;
                if(matrix[x][y] > 0) matrix[x][y] = Math.min(matrix[x][y],level); 
                q.offer(new int[]{x, y});
            }
        }
        
    }
    return matrix;
}

还有人用dfs,我觉得都是可以的,但用dfs时间复杂度可能会更高,还是bfs更容易理解。

当然,这个题目还可以用到动态规划,因为某一个点的离其最近的0相当于周围点离其最近0的最小距离加一,所以我们只需要正着反着各遍历一遍取最小即可:

    public int[][] updateMatrix(int[][] matrix) {
        int row = matrix.length;
        int col = matrix[0].length;
        // 第一次遍历,正向遍历,根据相邻左元素和上元素得出当前元素的对应结果
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (matrix[i][j] == 1) {
                    matrix[i][j] = Integer.MAX_VALUE;
                }
                if (i > 0 && matrix[i - 1][j] != Integer.MAX_VALUE) {
                    matrix[i][j] = Math.min(matrix[i][j], matrix[i - 1][j] + 1);
                }
                if (j > 0 && matrix[i][j - 1] != Integer.MAX_VALUE) {
                    matrix[i][j] = Math.min(matrix[i][j], matrix[i][j - 1] + 1);
                }
            }
        }
        // 第二次遍历,反向遍历,根据相邻右元素和下元素及当前元素的结果得出最终结果
        for (int i = row - 1; i >= 0; i--) {
            for (int j = col - 1; j >= 0; j--) {
                if (i < row - 1 && matrix[i + 1][j] != Integer.MAX_VALUE) {
                    matrix[i][j] = Math.min(matrix[i][j], matrix[i + 1][j] + 1);
                }
                if (j < col - 1 && matrix[i][j + 1] != Integer.MAX_VALUE) {
                    matrix[i][j] = Math.min(matrix[i][j], matrix[i][j + 1] + 1);
                }
            }
        }
        return matrix;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值