题目链接
题目描述:
在给定的网格中,每个单元格可以有以下三个值之一:
值 0 代表空单元格;
值 1 代表新鲜橘子;
值 2 代表腐烂的橘子。
每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。
返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1。
实例:
输入:[[2,1,1],[1,1,0],[0,1,1]]
输出:4
提示:
1 <= grid.length <= 10
1 <= grid[0].length <= 10
grid[i][j] 仅为 0、1 或 2
解题思路
题目要求返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数,实际就是求出腐烂橘子到所有新鲜橘子的最短路径。也就是说要用到队列实现BFS(广度优先搜索)。为了区分不同时间进入队列的腐烂橘子,在每一轮遍历开始前记录队列长度。按这个长度,根据队列特点,遍历循环长度之内的元素。
- 初始轮将所有腐烂的橘子放入队列中,记录新鲜橘子个数(可能有腐烂橘子污染不到的新鲜橘子)
- 进行BFS,将队首腐烂橘子出队并获取它的位置。对每个腐烂橘子的上下左右进行判断。若为新鲜橘子,就污染,同时减少新鲜橘子个数;否则,无作为。
- 某一轮遍历结束后,队列为空或新鲜橘子个数为0,则说明遍历结束。若存在未被污染的新鲜橘子,则返回-1;否则,说明污染成功,返回时间。
代码
struct Point{
int x; //行
int y; //列
};
class Solution {
public:
int orangesRotting(vector<vector<int>>& grid) {
queue<Point> queue_Grid;
int M = grid.size(); //获取行数
int N = grid[0].size(); //获取列数
int fresh_num = 0; //新鲜水果数量
//第一轮(初始化) 遍历数组
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++){
if(grid[i][j] == 2) //检测为腐烂水果,入队
queue_Grid.push(Point{i,j});
else if(grid[i][j] == 1) //检测为新鲜水果,记录数量
fresh_num++;
}
}
//1.一轮遍历队列中所有腐烂的水果;
//2.判断腐烂水果的四个方向,将他们变腐烂
//3.下一轮待遍历的腐烂水果进队
//直到某一轮过后无新鲜水果或队列为空(无腐烂水果进队)=》循环结束
int round = 0; //轮数or分钟数
while(fresh_num > 0 && !queue_Grid.empty()){
round++;
int n = queue_Grid.size(); //获取每一轮的队列长度
for(int i = 0; i < n; i++){
Point temp = queue_Grid.front();
queue_Grid.pop();
int r = temp.x, c = temp.y; //获取腐烂苹果的位置,行r列c
if(r - 1 >= 0 && grid[r-1][c] == 1){ //上
fresh_num--;
grid[r-1][c] = 2;
queue_Grid.push(Point{r-1,c});
}
if(r + 1 < M && grid[r+1][c] == 1){ //下
fresh_num--;
grid[r+1][c] = 2;
queue_Grid.push(Point{r+1,c});
}
if(c - 1 >= 0 && grid[r][c-1] == 1){ //左
fresh_num--;
grid[r][c-1] = 2;
queue_Grid.push(Point{r,c-1});
}
if(c + 1 < N && grid[r][c+1] == 1){ //右
fresh_num--;
grid[r][c+1] = 2;
queue_Grid.push(Point{r,c+1});
}
}
}
if(fresh_num > 0)
return -1;
else
return round;
}
};
如果有错误或者不严谨的地方,请务必给予指正,十分感谢。