📘题目描述
在给定的 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 。
💡解题思路:多源 BFS(队列传播)
🧠 核心思想
-
将所有初始腐烂橘子入队,作为多源 BFS 的起点
-
每分钟从队列中扩散一次(level = 一分钟)
-
将相邻的新鲜橘子标记为腐烂并入队
-
用变量
fresh
记录新鲜橘子总数,每腐烂一个就减一 -
若最终还有新鲜橘子剩下,则说明无法全部腐烂
✅代码实现
class Solution:
def orangesRotting(self, grid: List[List[int]]) -> int:
rows, cols = len(grid), len(grid[0])
queue = deque()
fresh = 0
# 初始化:记录所有腐烂橘子位置和新鲜橘子数量
for i in range(rows):
for j in range(cols):
if grid[i][j] == 2:
queue.append((i, j, 0)) # (行, 列, 当前分钟)
elif grid[i][j] == 1:
fresh += 1
time = 0 # 记录总耗时
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] # 上下左右
# BFS 开始
while queue:
r, c, minute = queue.popleft()
time = max(time, minute)
for dr, dc in directions:
nr, nc = r + dr, c + dc
if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] == 1:
grid[nr][nc] = 2 # 新鲜橘子变腐烂
fresh -= 1
queue.append((nr, nc, minute + 1))
return time if fresh == 0 else -1
⏱️复杂度分析
类型 | 复杂度 | 说明 |
---|---|---|
时间复杂度 | O(m × n) | 每个橘子最多入队一次 |
空间复杂度 | O(m × n) | 队列最多同时存储所有橘子的位置 |
🧱易错点总结
易错点 | 正确做法说明 |
---|---|
没有用队列记录时间 | 队列中附加 minute ,准确统计时间 |
忘记统计新鲜橘子数量 fresh | fresh 是是否成功腐烂的关键判断依据 |
没判断是否能全部腐烂(return -1) | 最后判断 if fresh == 0 决定返回值 |
🎯总结
-
本题是经典的 图遍历 - 多源 BFS 题型
-
类似的还有:
-
二进制矩阵中的最短路径
-
太平洋大西洋水流问题
-
太空船信号传递、蔓延问题等
-