题目描述
在给定的网格中,每个单元格可以有以下三个值之一:
- 值 0 代表空单元格;
- 值 1 代表新鲜橘子;
- 值 2 代表腐烂的橘子。
每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。
返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1。
示例 1:
- 输入:[[2,1,1],[1,1,0],[0,1,1]]
- 输出:4
示例 2:
- 输入:[[2,1,1],[0,1,1],[1,0,1]]
- 输出:-1
- 解释:左下角的橘子(第 2 行, 第 0 列)永远不会腐烂,因为腐烂只会发生在 4 个正向上。
示例 3:
- 输入:[[0,2]]
- 输出:0
- 解释:因为 0 分钟时已经没有新鲜橘子了,所以答案就是 0 。
提示:
1 <= grid.length <= 10
1 <= grid[0].length <= 10
grid[i][j]
仅为0
、1
或2
思路
使用队列存放坏橘子,每次BFS遍历时,记录当前队列大小,然后逐个拿出坏橘子向四个方向腐烂传播。
最初记录一下新鲜的橘子数量,每腐烂一个便减一,最后队列为空时,检查新鲜橘子的数量。若有,则返回-1;无则返回传播时间。
复杂度分析:
- 时间复杂度:O(nm)
即进行一次广度优先搜索的时间,其中 n=grid.length, m=grid[0].length 。
- 空间复杂度:O(nm)
广度优先搜索中队列里存放的状态最多不会超过 nm 个,最多需要 O(nm) 的空间,所以最后的空间复杂度为O(nm)。
解答
class Solution {
public:
int orangesRotting(vector<vector<int>>& grid) {
queue<pair<int,int>> rottedOranges;
vector<pair<int,int>> dir = {{0,1},{0,-1},{1,0},{-1,0}};
int freshCnt=0,time=0;
int width = grid[0].size(),height = grid.size();
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
if(grid[i][j]==1)
freshCnt++;
else if(grid[i][j]==2)
rottedOranges.push({i,j});
while(!rottedOranges.empty())
{
int n = rottedOranges.size();
bool rotOrange = false;
//bfs the queue once
for(int i=0;i<n;i++)
{
auto curOrange = rottedOranges.front();
rottedOranges.pop();
//check four directions
for(auto offset : dir)
{
int x=curOrange.first+offset.first;
int y=curOrange.second+offset.second;
if(x>=0 && y>=0 && x<height && y<width && grid[x][y] == 1)
{
freshCnt--;
grid[x][y]=2;
rottedOranges.push({x,y});
rotOrange = true;
}
}
}
//rot other oranges
if(rotOrange)
time++;
}
return freshCnt?-1:time;
}
};