Leetcode994:腐烂的橘子——多源广度优先搜索—有趣的题目
这篇文章发布已经超过两年,部分工具、版本或观点可能已经变化,请结合最新信息判断。
题目
https://leetcode-cn.com/problems/rotting-oranges/
这道题就接着733题做刚刚好。正好介于有点思路但又写不出来中间,属于够一够脚尖才能实现的目标。
题解
解题思路
这道题很明显要使用广度优先搜索,搜索的目标是每个腐烂橘子周围的新鲜橘子。相较于733题图像渲染来说,这道题由一个搜索源点变成了可能有多个源点。而且你得一轮一轮去搜索,并统计出搜索的轮数。
如果只用一个队列的话,难以区分队列中的烂橘子是在哪一轮烂掉的。所以本菜鸡突发奇想,用两个队列交替push。例如:第一轮把烂橘子push给que队列,第二轮push给newque队列,清空que队列,第三轮再push给que队列…以此类推。
官方题解只用了一个队列,它并不是在搜索时区分第几轮的。而是使用了一个dis[][]数组,记录了每一个橘子相较于上一个橘子腐烂时间+1。也非常巧妙。
代码
class Solution {
public:
int orangesRotting(vector<vector<int>>& grid) {
vector<int> dx = {-1, 1, 0, 0};
vector<int> dy = {0, 0, -1, 1};
queue<pair<int,int>> que;
queue<pair<int,int>> newque; // 定义了两个队列
int maxrow = grid.size();
int maxcol = grid[0].size();
int fresh = 0; // 新鲜橘子
// 先把坏橘子入队
for(int i=0; i<maxrow; i++){
for(int j=0;j<maxcol; j++){
if(grid[i][j] == 2){
que.emplace(i,j);
}else if(grid[i][j] == 1){
fresh += 1;
}
}
}
newque = que;
int minute = 0;
// 一轮一轮地搜索腐烂橘子四周的新鲜橘子
while(!newque.empty()){
minute += 1;
que = newque;
newque = queue<pair<int,int>>(); // 清空
while(!que.empty()){
pair<int,int> rot = que.front();que.pop();
for(int i=0;i<4;i++){
int x = rot.first+dx[i];
int y = rot.second+dy[i];
if(x>=0 && x<maxrow && y>=0 && y<maxcol && grid[x][y]==1){
grid[x][y] = 2;
fresh -= 1;
newque.emplace(x,y);
}
}
}
}
if(fresh){return -1;} // 检查一下还有没有腐烂橘子
return max(0,minute-1);
}
};
细节:
- 最开始把坏橘子找出来的同时顺便可以把新鲜橘子的总数找出来。在搜索时顺便统计一下坏掉橘子的数量,相减后就能知道几轮下来还有没有新鲜的橘子了。
- 我这样写代码把最初坏的橘子也算上消耗了一分钟时间,等于多算了一分钟,最后要把minute-1。但由于minute初值设置为0,所以可能会有-1的情况,此时取0就可。(我现在写题解的时候突然发现这个-1貌似没影响qwq)
看了下其他人的题解没有用我这种双队列方法的,哈哈,还特意发了个题解显摆一下,作者竟我自己😂
评论区已延迟加载滑到评论区附近时会自动加载,也可以现在手动打开。



