leetcode
leetcode 501 ~ 550
01 矩阵

01 矩阵

难度:

标签:

题目描述

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

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

 

示例 1:

输入:mat = [[0,0,0],[0,1,0],[0,0,0]]
输出:[[0,0,0],[0,1,0],[0,0,0]]

示例 2:

输入:mat = [[0,0,0],[0,1,0],[1,1,1]]
输出:[[0,0,0],[0,1,0],[1,2,1]]

 

提示:

  • m == mat.length
  • n == mat[i].length
  • 1 <= m, n <= 104
  • 1 <= m * n <= 104
  • mat[i][j] is either 0 or 1.
  • mat 中至少有一个

代码结果

运行时间: 99 ms, 内存: 18.2 MB


/* 
 * 题目思路: 
 * 使用Java Stream API处理和计算矩阵中各个元素到最近0的距离。 
 * 1. 使用Queue储存所有为0的点,将其余点设为无穷大(Integer.MAX_VALUE)。 
 * 2. BFS遍历矩阵,用Stream进行迭代和处理。 
 */ 
import java.util.*; 
import java.util.stream.*; 
 
public class Solution { 
    public int[][] updateMatrix(int[][] mat) { 
        int m = mat.length; 
        int n = mat[0].length; 
        int[][] dist = new int[m][n]; 
        Queue<int[]> queue = new LinkedList<>(); 
        IntStream.range(0, m).forEach(i -> IntStream.range(0, n).forEach(j -> { 
            if (mat[i][j] == 0) { 
                queue.offer(new int[]{i, j}); 
                dist[i][j] = 0; 
            } else { 
                dist[i][j] = Integer.MAX_VALUE; 
            } 
        })); 
        int[][] dirs = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; 
        while (!queue.isEmpty()) { 
            int[] cell = queue.poll(); 
            Arrays.stream(dirs).forEach(dir -> { 
                int r = cell[0] + dir[0]; 
                int c = cell[1] + dir[1]; 
                if (r >= 0 && r < m && c >= 0 && c < n && dist[r][c] > dist[cell[0]][cell[1]] + 1) { 
                    queue.offer(new int[]{r, c}); 
                    dist[r][c] = dist[cell[0]][cell[1]] + 1; 
                } 
            }); 
        } 
        return dist; 
    } 
}

解释

方法:

该题解采用了广度优先搜索(BFS)的方法。首先,遍历整个矩阵,将所有为0的位置坐标存储到一个列表中,这些位置作为BFS的起始节点。使用一个队列来执行BFS,队列的初始内容是所有0的位置。在BFS过程中,从队列中取出位置,并将其四周的相邻位置(上、下、左、右)加入队列中,同时记录从起始节点到当前节点的距离。通过这种方式,可以确保每个元素到最近的0的距离被正确计算并存储在结果矩阵中。

时间复杂度:

O(m * n)

空间复杂度:

O(m * n)

代码细节讲解

🦆
为什么在算法中首先需要将矩阵中所有的0的位置存储起来作为BFS的起始节点?
在这个问题中,我们需要找到矩阵中每个1的位置到最近的0的距离。如果我们从每个1的位置开始进行BFS搜索0,将非常低效,因为这需要从每个1重复搜索整个矩阵。相反,如果我们从所有0的位置开始BFS,我们可以同时更新它们周围的1的最短距离。这种方法使得每个位置只被访问一次,从而显著提高效率。
🦆
在BFS过程中,你是如何确保不会重复访问同一个节点?
为了确保不会重复访问同一个节点,算法中使用了一个名为`visited`的集合来记录已经访问过的节点。每次我们从队列中取出一个节点,我们都会检查它是否已经被访问过。如果没有被访问过,我们才会将其相邻的节点加入到队列中,并将这个节点标记为已访问。这样可以避免重复处理同一个节点,从而保证了效率和正确性。
🦆
你的算法中提到了一个变量`level`,它是如何帮助记录从起始节点到当前节点的距离的?
`level`变量在算法中用来追踪从所有0的位置(起始点)到当前处理的节点的距离。在BFS中,每一层(即每一轮循环)都代表了从起点向外扩展一层,因此每处理完一层,`level`就会增加1。这样,当我们访问到一个1的位置时,其在`ans`矩阵中对应的值即为该位置到最近0的距离,也就是当前的`level`值。

相关问题