题目
在给定的网格中,每个单元格可以有以下三个值之一:
值 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分钟。
- 用队列先保存所有烂橘子的坐标,用size代表队列中烂橘子的数量。用good表示好橘子的数量。
- 将队列中的烂橘子取出,size自减1,将周围的好橘子感染。被好橘子被感染,good减一。被感染的好橘子再放到队列中。当size变为0的时候,说明第一批烂橘子已经感染完了。如果此时队列为空,说明没有好橘子变成烂橘子,则循环可以结束。如果此时队列不为空,则size设置为此时队列的长度,继续循环。
- 循环结束时,判断好橘子数good是否为0,如果不为0,则返回-1。
代码
class Solution {
private:
int rows, cols;
public:
int orangesRotting(vector<vector<int>>& grid) {
if ( grid.size() == 0 ) return 0;
rows = grid.size();
cols = grid[0].size();
vector<vector<int>> pattern = { {0, 1}, {0, -1}, {1, 0}, {-1, 0} };
int ans = 0;
queue<vector<int>> q;
int goodOranges = 0; // 好橘子的数量
// 找到所有腐烂的橘子
for ( int row = 0; row < rows; ++row ) {
for ( int col = 0; col < cols; ++col ) {
if ( grid[row][col] == 2 )
q.push( {row, col} );
else if ( grid[row][col] == 1 )
++goodOranges;
}
}
int size = q.size(); // 0 时刻怀橘子的数量
while ( !q.empty() ) {
while ( size-- ) {
vector<int> pos = q.front();
q.pop();
for ( auto& vec : pattern ) {
int nRow = vec[0] + pos[0];
int nCol = vec[1] + pos[1];
if ( isValid( nRow, nCol ) && grid[nRow][nCol] == 1 ) {
grid[nRow][nCol] = 2;
q.push( {nRow, nCol } );
--goodOranges; // 新增一个坏橘子,减少一个好橘子。
}
}
}
if ( q.empty() ) break; // 如果q.empty()为空,说明没新增腐烂的橘子
++ans;
size = q.size(); // 下一时刻坏橘子的数量
}
if ( goodOranges != 0 ) ans = -1; // 还有好橘子
return ans;
}
bool isValid( int row, int col ) {
return row >=0 && row < rows && col >=0 && col < cols;
}
};