Leetcode 542. 01 矩阵

2023-03-13  本文已影响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的思路。

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

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两种方法来做,两种方法都比较直观。有几点需要注意:

上一篇 下一篇

猜你喜欢

热点阅读