994. 腐烂的橘子
大约 2 分钟
994. 腐烂的橘子
题目
描述: 在给定的 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解题思路
核心方法
广度优先搜索(BFS):
- 初始化队列:将所有腐烂的橘子的坐标加入队列,作为 BFS 的起点。
- 统计新鲜橘子数量:遍历网格,统计新鲜橘子的数量
count。 - 层次遍历:每次处理队列中所有当前层的腐烂橘子,将其相邻的新鲜橘子标记为腐烂,并加入下一层队列,同时减少新鲜橘子数量。
- 记录时间:每处理完一层,时间
ans加 1。 - 判断结果:若最终新鲜橘子数量为 0,返回时间
ans;否则返回-1。
代码实现
BFS 实现(Java)
import java.util.*;
class Solution {
public int orangesRotting(int[][] grid) {
Queue<int[]> queue = new LinkedList<>();
int count = 0;
int rows = grid.length;
int cols = grid[0].length;
// 初始化队列和新鲜橘子数量
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (grid[i][j] == 2) {
queue.add(new int[]{i, j});
} else if (grid[i][j] == 1) {
count++;
}
}
}
if (count == 0) return 0;
int ans = 0;
// 四个方向
int[][] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
while (!queue.isEmpty() && count > 0) {
ans++;
int size = queue.size();
for (int i = 0; i < size; i++) {
int[] curr = queue.poll();
int x = curr[0];
int y = curr[1];
for (int[] dir : dirs) {
int nx = x + dir[0];
int ny = y + dir[1];
if (nx >= 0 && nx < rows && ny >= 0 && ny < cols && grid[nx][ny] == 1) {
grid[nx][ny] = 2;
count--;
queue.add(new int[]{nx, ny});
}
}
}
}
return count == 0 ? ans : -1;
}
}复杂度分析
- 时间复杂度:
O(m * n),其中m和n分别是网格的行数和列数。每个单元格最多被访问一次。 - 空间复杂度:
O(m * n),最坏情况下(网格全为腐烂橘子),队列大小为O(m * n)。
总结
- BFS 是解决这类扩散类问题的最优方法,通过层次遍历确保每一分钟的腐烂过程被准确模拟。
- 初始化时将所有腐烂橘子加入队列,避免了多次启动 BFS,提升了效率。
- 新鲜橘子数量的统计和动态更新,确保了最终结果的正确性。
