墙与门
难度:
标签:
题目描述
代码结果
运行时间: 67 ms, 内存: 19.5 MB
/*
* 题目:墙与门
* 你被给定一个 m × n 的二维网格,网格中有以下几种可能的初始化值:
* -1 表示墙或是障碍物
* 0 表示一扇门
* INF 无限表示一个空的房间
* 你需要填充每个空房间到最近门的距离,如果无法到达门,则填充 INF
*
* 思路:
* 使用广度优先搜索(BFS)从每个门(值为0)开始,将距离依次填充到周围的空房间
*/
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.stream.IntStream;
public class WallsAndGatesStream {
private static final int INF = Integer.MAX_VALUE;
public void wallsAndGates(int[][] rooms) {
if (rooms == null || rooms.length == 0) return;
int m = rooms.length;
int n = rooms[0].length;
Queue<int[]> queue = new LinkedList<>();
// 将所有的门加入队列
IntStream.range(0, m).forEach(i ->
IntStream.range(0, n).filter(j -> rooms[i][j] == 0).forEach(j -> queue.offer(new int[]{i, j}))
);
// 四个方向
int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
// BFS 处理
while (!queue.isEmpty()) {
int[] point = queue.poll();
int row = point[0];
int col = point[1];
Arrays.stream(directions).forEach(direction -> {
int newRow = row + direction[0];
int newCol = col + direction[1];
// 检查边界和是否是空房间
if (newRow >= 0 && newRow < m && newCol >= 0 && newCol < n && rooms[newRow][newCol] == INF) {
// 更新距离并将新的房间加入队列
rooms[newRow][newCol] = rooms[row][col] + 1;
queue.offer(new int[]{newRow, newCol});
}
});
}
}
}
解释
方法:
这个题解使用广度优先搜索(BFS)的方法来解决问题。首先,遍历整个rooms矩阵,找到所有的门(值为0的格子),并将它们的坐标添加到一个队列search_queue中。然后,不断从队列中取出格子,对于每个格子,检查其四个相邻的格子。如果相邻格子是空的(值为inf),就将其距离设置为当前格子的距离+1,并将相邻格子加入队列。这样不断扩展,直到队列为空,所有可达的空格子都被填入正确的距离值。
时间复杂度:
O(m*n)
空间复杂度:
O(m*n)
代码细节讲解
🦆
为什么在BFS解法中,一开始只将门的位置加入搜索队列,而不是所有的格子?
▷🦆
在BFS扩展过程中,更新相邻格子的距离时,有没有可能出现重复更新同一个格子的情况?如果有,这会对算法的效率产生什么影响?
▷🦆
当矩阵中不包含任何门时,题解的BFS方法会如何处理?是否有必要对这种情况进行特殊处理来提升效率?
▷相关问题
被围绕的区域
给你一个
m x n
的矩阵 board
,由若干字符 'X'
和 'O'
,找到所有被 'X'
围绕的区域,并将这些区域里所有的 'O'
用 'X'
填充。
示例 1:

输入:board = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]] 输出:[["X","X","X","X"],["X","X","X","X"],["X","X","X","X"],["X","O","X","X"]] 解释:被围绕的区间不会存在于边界上,换句话说,任何边界上的'O'
都不会被填充为'X'
。 任何不在边界上,或不与边界上的'O'
相连的'O'
最终都会被填充为'X'
。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
示例 2:
输入:board = [["X"]] 输出:[["X"]]
提示:
m == board.length
n == board[i].length
1 <= m, n <= 200
board[i][j]
为'X'
或'O'
岛屿数量
给你一个由 '1'
(陆地)和 '0'
(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入:grid = [ ["1","1","1","1","0"], ["1","1","0","1","0"], ["1","1","0","0","0"], ["0","0","0","0","0"] ] 输出:1
示例 2:
输入:grid = [ ["1","1","0","0","0"], ["1","1","0","0","0"], ["0","0","1","0","0"], ["0","0","0","1","1"] ] 输出:3
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j]
的值为'0'
或'1'
腐烂的橘子
在给定的 m x n
网格 grid
中,每个单元格可以有以下三个值之一:
- 值
0
代表空单元格; - 值
1
代表新鲜橘子; - 值
2
代表腐烂的橘子。
每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。
返回 直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1
。
示例 1:
输入:grid = [[2,1,1],[1,1,0],[0,1,1]] 输出:4
示例 2:
输入:grid = [[2,1,1],[0,1,1],[1,0,1]] 输出:-1 解释:左下角的橘子(第 2 行, 第 0 列)永远不会腐烂,因为腐烂只会发生在 4 个方向上。
示例 3:
输入:grid = [[0,2]] 输出:0 解释:因为 0 分钟时已经没有新鲜橘子了,所以答案就是 0 。
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 10
grid[i][j]
仅为0
、1
或2