解题思路:
- 同一时刻,烂橘子会同时开始传播,所以用深度遍历就不适用了。
- 虽然是网格,但是烂橘子传播就像是树层序遍历到叶子结点,遍历每一层的时候,就需要时间+1,所以可以抽象成树的层序遍历,不断遍历到叶子结点所需要花费的时间。
- 需要获得条件:新鲜橘子数量;初始烂橘子的队列。
- 层序遍历循环的条件:烂橘子队列不为空 以及 还存在新鲜的橘子。
- 遍历中需要执行:
- 花费时间+1
- 遍历当前队列中的烂橘子
- 传播烂橘子。将烂橘子周围的新鲜橘子加入到烂橘子队列中,并将其变成烂橘子,并将新鲜橘子数量-1。
- 返回条件:如果遍历完烂橘子队列了,还有新鲜橘子,那么就返回-1。否则,返回遍历整个烂橘子树的总时间。
class Solution {
public int orangesRotting(int[][] grid) {
int M = grid.length;
int N = grid[0].length;
int orangeNums = 0; // 新鲜橘子的数量
int time = 0; // 所需要花费的时间`
Queue<int[]> queue = new LinkedList<>(); // 存放烂橘子队列
// 获得烂橘子的队列与新鲜橘子个数
for (int x = 0; x < M; x++) {
for (int y = 0; y < N; y++) {
if (grid[x][y] == 2) {
queue.add(new int[]{x, y});
} else if (grid[x][y] == 1) {
orangeNums++;
}
} // for.x
} // for.x
// 开始层序遍历,传播烂橘子
while (orangeNums > 0 && !queue.isEmpty()) { // 没有新鲜橘子 或者 队列为空了 -> 退出循环
time++;
int n = queue.size();
while (n > 0) {
n--; // 弹出了一个烂橘子了,队列循环-1
// 获得烂橘子的坐标
int[] rotten = queue.poll();
int x = rotten[0];
int y = rotten[1];
// 传播腐烂
// 上
if (x - 1 >= 0 && grid[x - 1][y] == 1) {
orangeNums--;
grid[x - 1][y] = 2;
queue.add(new int[]{x - 1, y});
}
// 下
if (x + 1 < M && grid[x + 1][y] == 1) {
orangeNums--;
grid[x + 1][y] = 2;
queue.add(new int[]{x + 1, y});
}
// 左
if (y - 1 >= 0 && grid[x][y - 1] == 1) {
orangeNums--;
grid[x][y - 1] = 2;
queue.add(new int[] {x, y - 1});
}
// 右
if (y + 1 < N && grid[x][y + 1] == 1) {
orangeNums--;
grid[x][y + 1] = 2;
queue.add(new int[] {x, y + 1});
}
} // while close
} // while close
return orangeNums > 0 ? -1 : time;
} // orangesRotting
}