美文网首页
Leetcode 542. 01 矩阵

Leetcode 542. 01 矩阵

作者: 尹学姐 | 来源:发表于2023-03-13 21:59 被阅读0次

题目

Given an m x n binary matrix mat, return the distance of the nearest 0 for each cell.

The distance between two adjacent cells is 1.

Example1:


image.png

Input: mat = [[0,0,0],[0,1,0],[0,0,0]]
Output: [[0,0,0],[0,1,0],[0,0,0]]

Example2:


image.png

Input: mat = [[0,0,0],[0,1,0],[1,1,1]]
Output: [[0,0,0],[0,1,0],[1,2,1]]

解题思路

这道题的要求是求出每个cell到0的距离,可以用BFS和DP两种方法来做。

方法 时间复杂度 空间复杂度
BFS O(mn) O(mn)
DP O(4mn) O(1)

1. BFS

BFS的思路是,找到起点节点,然后以起点为圆心,一层一层扩散的方式,遍历所有的节点。

BFS的实现模板,就是使用队列来实现。

模板代码如下:

   private void bfs(Node root){
        Queue<Node> queue = new LinkedList<>();
        // 先把起点加入队列
        queue.offer(root);
        while(!queue.isEmpty()){
            int node = queue.poll();
            // 把所有的下一层级的孩子,加入队列
            for(Node child : node.children){
                queue.offer(child);
            }
        }
    }

这道题是典型的BFS的思路。

  • 题目要求节点到0的距离,所以我们知道,所有0节点的值都是0。那我们可以把这个0节点作为起点,先加入队列。
  • 记录一个全局的变量level,表示节点离0节点的层数。
  • 然后找到0节点周围的所有1节点,遍历他们,并设置层数level,然后将这些节点加入队列,继续遍历。
  • 直到所有的节点都遍历完。

注意:为了防止重复遍历死循环,已经遍历过的节点,不要重复遍历。

class Solution {
    public int[][] updateMatrix(int[][] mat) {
        int n = mat.length, m = mat[0].length;
        int[][] res = new int[n][m];
        // 保存已经遍历过的节点
        boolean[][] visited = new boolean[n][m];
        // BFS模板代码
        Queue<int[]> queue = new LinkedList<>();
        for(int i = 0 ; i < n; i++){
            for(int j = 0; j < m; j++){
                // 先把所有的0节点加入queue,作为起点
                if(mat[i][j] == 0){
                    visited[i][j] = true;
                    queue.add(new int[]{i, j});   
                }
            }
        }
        // 遍历四个方向的节点
        int[][] directions = {{-1,0}, {1,0}, {0,-1}, {0,1}};
        while(!queue.isEmpty()){
            int[] cur = queue.poll();
            int i = cur[0], j = cur[1];
            for(int k = 0; k < directions.length; k++){
                int r = i + directions[k][0];
                int c = j + directions[k][1];
                // 判断坐标值是否有效 & 是否访问过
                if(r >= 0 && r < n && c >= 0 && c < m && !visited[r][c]){
                    res[r][c] = res[i][j] + 1;
                    visited[r][c] = true;
                    queue.add(new int[]{r, c});
                }
            }
        }
        return res;
    }
}

2. DP

这道题很直接得能想到用DP去做。递推公式如下:

如果mat[i][j] == 0dp[i][j] = 0
如果mat[i][j] != 0dp[i][j] = 1 + min(dp[i-1][j], dp[i+1][j], [dp[i][j-1], dp[i][j+1])

一般DP都是从一个方向开始,做DP。而这道题需要从四个方向分别做DP,最后取DP结果的最小值。

class Solution {
    public int[][] updateMatrix(int[][] mat) {
        int n = mat.length;
        int m = mat[0].length;
        int[][] dp = new int[n][m];
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(mat[i][j] == 0){
                    dp[i][j] = 0;
                }else{
                    dp[i][j] = Math.max(n, m) + 1;
                }
            }
        }
        // 从左上方来的
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(i > 0){
                    dp[i][j] = Math.min(dp[i][j], dp[i-1][j] + 1);
                }
                if(j > 0){
                    dp[i][j] = Math.min(dp[i][j], dp[i][j-1] + 1);
                }
            }
        }
        // 从左下方来
        for(int i = n - 1; i >= 0; i--){
            for(int j = 0; j < m; j++){
                if(i < n-1){
                    dp[i][j] = Math.min(dp[i][j], dp[i+1][j] + 1);
                }
                if(j > 0){
                    dp[i][j] = Math.min(dp[i][j], dp[i][j-1] + 1);
                }
            }
        }
        // 从右上方来
        for(int i = 0; i < n; i++){
            for(int j = m-1; j >= 0; j--){
                if(i > 0){
                    dp[i][j] = Math.min(dp[i][j], dp[i-1][j] + 1);
                }
                if(j < m-1){
                    dp[i][j] = Math.min(dp[i][j], dp[i][j+1] + 1);
                }
            }
        }
        // 从右下方来
        for(int i = n-1; i >= 0; i--){
            for(int j = m-1; j >= 0; j--){
                if(i < n-1){
                    dp[i][j] = Math.min(dp[i][j], dp[i+1][j] + 1);
                }
                if(j < m-1){
                    dp[i][j] = Math.min(dp[i][j], dp[i][j+1] + 1);
                }
            }
        }
        return dp;
    }
}

总结

这道题我们用了BFS和DP两种方法来做,两种方法都比较直观。有几点需要注意:

  • BFS采用以0为起点的方法,多路同时进行。为了避免发生死循环,需要记录已经访问过的节点。
  • DP需要从四个方向做DP,然后取最小值作为结果,如果只从一个方向DP,结果不是最优解。

相关文章

  • LeetCode 542. 01 矩阵

    542. 01 矩阵 题目来源:https://leetcode-cn.com/problems/01-matri...

  • ARTS打卡第一周

    ARTS打卡第一周 Algorithm:每周至少做一个 leetcode 的算法题 542. 01 矩阵 Revi...

  • 542. 01 矩阵

    题目描述 给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。 两个相邻元素间的距离为 1 。 ...

  • 542. 01矩阵

    题目描述 给定一个由0和1组成的矩阵,找出每个元素到最近0的距离,相邻元素间的距离为1。例如:输入 输出 注意: ...

  • 542. 01矩阵(Python)

    题目 难度:★★☆☆☆类型:数组方法:二分法 力扣链接请移步本题传送门[https://leetcode-cn.c...

  • LeetCode:01矩阵

    542. 01 矩阵 给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。两个相邻元素间的距离为...

  • BFS / DFS 典型例题

    图的BFS: leetcode:1162 地图分析leetcode:542 01矩阵 树的BFS: 图的DFS: ...

  • LeetCode-01矩阵

    给定一个由0和1组成的矩阵,找出每个元素到最近的 0 的距离两个相邻元素间的距离为 1 。 快速浏览 超级原点 广...

  • leetcode-01矩阵

    这道题感觉很难理解,用了BFS方法。先是将位置为0的入队列,然后一圈圈扩展,位置为1的入队列。看下面链接详解。 利...

  • LeetCode-74-搜索二维矩阵

    LeetCode-74-搜索二维矩阵 74. 搜索二维矩阵[https://leetcode-cn.com/pro...

网友评论

      本文标题:Leetcode 542. 01 矩阵

      本文链接:https://www.haomeiwen.com/subject/xwajldtx.html