612 字
3 分钟
LeetCode-994.腐烂的橘子

图论#

994. 腐烂的橘子

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

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

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

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


示例 1:

img

输入: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的解法

思路:

  1. 容易被题目示例误导的一点是:这里的烂橘子是可以不止一个的,这就与 200. 岛屿数量 有所不同,从“单源”改为“多源”,所以需要先遍历一次网格,把所有初始状态就是 2 的烂橘子全部塞进初始队列中。它们处于同一“层”,地位平等,会像水波纹一样同时向外扩散。

  2. 就是rottedThisMinute = true的作用,我们会疑惑时间不是一直在增加的吗,为什么需要这个?

    这是因为会遇到像示例3的状况,它们被从 queue 中取出来,此时,它们周围已经没有任何新鲜橘子了(或者被墙挡住了),但程序还会检查,所以这段时间是不需要或者说是没意义的。

func orangesRotting(grid [][]int) int {
if len(grid) == 0 {
return 0
}
m, n := len(grid), len(grid[0])
queue := [][]int{}
fresh := 0
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if grid[i][j] == 2 {
queue = append(queue, []int{i, j})
}
if grid[i][j] == 1 {
fresh++
}
}
}
if fresh == 0 {
return 0
}
time := 0
dirs := [][]int{{0, 1}, {0, -1}, {1, 0}, {-1, 0}}
for len(queue) != 0 {
size := len(queue)
rottedThisMinute := false
for i := 0; i < size; i++ {
cur := queue[0]
queue = queue[1:]
row, col := cur[0], cur[1]
for _, v := range dirs {
nr, nc := v[0]+row, v[1]+col
if nr >= 0 && nr < m && nc >= 0 && nc < n && grid[nr][nc] == 1 {
grid[nr][nc] = 2
queue = append(queue, []int{nr, nc})
fresh--
rottedThisMinute = true
}
}
}
if rottedThisMinute == true {
time++
}
}
if fresh != 0 {
return -1
}
return time
}
LeetCode-994.腐烂的橘子
https://sheep44044.github.io/posts/算法/图论/leetcode-994腐烂的橘子/
作者
sheep44044
发布于
2026-03-19
许可协议
CC BY-NC-SA 4.0