Leetcode994.腐烂的橘子

在给定的 m x n 网格 grid 中,每个单元格可以有以下三个值之一:

  • 0 代表空单元格;
  • 1 代表新鲜橘子;
  • 2 代表腐烂的橘子。

每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。

返回 直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1

示例 1:

1
2
输入:grid = [[2,1,1],[1,1,0],[0,1,1]]
输出:4

示例 2:

1
2
3
输入:grid = [[2,1,1],[0,1,1],[1,0,1]]
输出:-1
解释:左下角的橘子(第 2 行, 第 0 列)永远不会腐烂,因为腐烂只会发生在 4 个方向上。

示例 3:

1
2
3
输入:grid = [[0,2]]
输出:0
解释:因为 0 分钟时已经没有新鲜橘子了,所以答案就是 0 。

解法:使用BFS

BFS 可以看成是层序遍历。从某个结点出发,BFS 首先遍历到距离为 1 的结点,然后是距离为 2、3、4…… 的结点。因此,BFS 可以用来求最短路径问题。BFS 先搜索到的结点,一定是距离最近的结点。

再看看这道题的题目要求:返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。翻译一下,实际上就是求腐烂橘子到所有新鲜橘子的最短路径。那么这道题使用 BFS,应该是毫无疑问的了。

BFS的模板:

1
2
3
4
5
while queue 非空:
node = queue.pop()
for node 的所有相邻结点 m:
if m 未访问过:
queue.push(m)

answer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class Solution(object):
def orangesRotting(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
M = len(grid)
N = len(grid[0])
queue = []

count = 0
for r in range(M):
for c in range(N):
if grid[r][c] == 1:
count += 1
elif grid[r][c] == 2:
queue.append((r,c))

round = 0
while count > 0 and len(queue) > 0:
round += 1
n = len(queue)
for i in range(n):
r,c = queue.pop(0)
if r-1 >= 0 and grid[r-1][c] == 1:
grid[r-1][c] = 2
count -= 1
queue.append((r-1,c))
if r+1< M and grid[r+1][c] == 1:
grid[r+1][c] =2
count -= 1
queue.append((r+1,c))
if c-1 >= 0 and grid[r][c-1] == 1:
grid[r][c-1] = 2
count -= 1
queue.append((r,c-1))
if c+1 < N and grid[r][c+1] == 1:
grid[r][c+1] = 2
count -= 1
queue.append((r,c+1))
if count > 0:
return -1
else:
return round