主题

看示例 1:
- 统计所有初始就腐烂的橘子的位置,加到列表
中,现在 。 - 初始化答案
。模拟橘子腐烂的过程,不断循环,直到没有新鲜橘子,或者 为空。 - 答案加一,在第
分钟,遍历 中橘子的四方向相邻的新鲜橘子,把这些橘子腐烂, 更新为这些橘子的位置,现在 。 - 答案加一,在第
分钟,遍历 中橘子的四方向相邻的新鲜橘子,把这些橘子腐烂, 更新为这些橘子的位置,现在 。 - 答案加一,在第
分钟,遍历 中橘子的四方向相邻的新鲜橘子,把这些橘子腐烂, 更新为这些橘子的位置,现在 。 - 答案加一,在第
分钟,遍历 中橘子的四方向相邻的新鲜橘子,把这些橘子腐烂, 更新为这些橘子的位置,现在 。 - 由于没有新鲜橘子,退出循环。
为了判断是否有永远不会腐烂的橘子(如示例 2),我们可以统计初始新鲜橘子的个数
代码实现时,在 BFS 中要将 grid[i][j] = 2 这行代码试试。
关于 BFS 的原理,请看【基础算法精讲 13】。
答疑
问:如果代码不在 while 中判断
答:会在腐烂完所有新鲜橘子后,多循环一次。这会导致
python
class Solution:
def orangesRotting(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
fresh = 0
q = []
for i, row in enumerate(grid):
for j, x in enumerate(row):
if x == 1:
fresh += 1 # 统计新鲜橘子个数
elif x == 2:
q.append((i, j)) # 一开始就腐烂的橘子
ans = 0
while q and fresh:
ans += 1 # 经过一分钟
tmp = q
q = []
for x, y in tmp: # 已经腐烂的橘子
for i, j in (x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1): # 四方向
if 0 <= i < m and 0 <= j < n and grid[i][j] == 1: # 新鲜橘子
fresh -= 1
grid[i][j] = 2 # 变成腐烂橘子
q.append((i, j))
return -1 if fresh else anscpp
// C++ 版待补充cpp
class Solution {
int DIRECTIONS[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; // 四方向
public:
int orangesRotting(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size();
int fresh = 0;
vector<pair<int, int>> q;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
fresh++; // 统计新鲜橘子个数
} else if (grid[i][j] == 2) {
q.emplace_back(i, j); // 一开始就腐烂的橘子
}
}
}
int ans = 0;
while (fresh && !q.empty()) {
ans++; // 经过一分钟
auto tmp = move(q); // move 后 q 为空
for (auto& [x, y] : tmp) { // 已经腐烂的橘子
for (auto& d : DIRECTIONS) { // 四方向
int i = x + d[0], j = y + d[1];
if (0 <= i && i < m && 0 <= j && j < n && grid[i][j] == 1) { // 新鲜橘子
fresh--;
grid[i][j] = 2; // 变成腐烂橘子
q.emplace_back(i, j);
}
}
}
}
return fresh ? -1 : ans;
}
};复杂度分析
- 时间复杂度:
,其中 和 分别为 的行数和列数。 - 空间复杂度:
。
变形题(2025.7.16 添加)
- 你可以把至多
个 改成 ,最小化最终新鲜橘子个数。 - 你可以把至多
个 改成 ,最小化最终新鲜橘子个数。 - 你可以把至多
个 改成 ,最大化最终新鲜橘子个数。 - 你可以把至多
个 改成 ,最大化最终新鲜橘子个数。
欢迎在评论区分享你的思路/代码。
更多相似题目,见下面网格图题单中的 BFS。
分类题单
- 滑动窗口与双指针(定长/不定长/单序列/双序列/三指针/分组循环)
- 二分算法(二分答案/最小化最大值/最大化最小值/第K小)
- 单调栈(基础/矩形面积/贡献法/最小字典序)
- 网格图(DFS/BFS/综合应用)
- 位运算(基础/性质/拆位/试填/恒等式/思维)
- 图论算法(DFS/BFS/拓扑排序/基环树/最短路/最小生成树/网络流)
- 动态规划(入门/背包/划分/状态机/区间/状压/数位/数据结构优化/树形/博弈/概率期望)
- 常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树)
- 数学算法(数论/组合/概率期望/博弈/计算几何/随机算法)
- 贪心与思维(基本贪心策略/反悔/区间/字典序/数学/思维/脑筋急转弯/构造)
- 链表、二叉树与回溯(前后指针/快慢指针/DFS/BFS/直径/LCA/一般树)
- 字符串(KMP/Z函数/Manacher/字符串哈希/AC自动机/后缀数组/子序列自动机)
欢迎关注 B站@灵茶山艾府