leetcode原题链接: 腐烂的橘子
上一篇:HOT51-岛屿数量
下一篇:HOT53-课程表
题目描述
在给定的 m x n
网格 grid
中,每个单元格可以有以下三个值之一:
- 值
0
代表空单元格; - 值
1
代表新鲜橘子; - 值
2
代表腐烂的橘子。
每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。
返回 直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1
。
示例 1:
输入:grid = [[2,1,1],[1,1,0],[0,1,1]] 输出:4
示例 2:
输入:grid = [[2,1,1],[0,1,1],[1,0,1]] 输出:-1 解释:左下角的橘子(第 2 行, 第 0 列)永远不会腐烂,因为腐烂只会发生在 4 个正向上。
示例 3:
输入:grid = [[0,2]] 输出:0 解释:因为 0 分钟时已经没有新鲜橘子了,所以答案就是 0 。
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 10
grid[i][j]
仅为0
、1
或2
解题方法:采用类似于树的层次遍历的方法,每次扩散一层,扩散某层某个节点就是将腐烂节点的上、下、左、右四个方向的新鲜橘子放入扩散队列中,扩散的层数就是最终的分钟数。最后还需要判断下所有的橘子是否全部腐烂。
C++代码
#include <iostream>
#include <vector>
#include <queue> //std::queue
#include <utility> //std::pair
class Solution {
public:
int orangesRotting(std::vector<std::vector<int>>& grid) {
int rnum = grid.size();
int cnum = grid[0].size();
std::queue<std::pair<int, int>> q;
int fresh_cnt = 0;//保存新鲜橘子的个数
for (int i = 0; i < rnum; i++) {
for (int j = 0; j < cnum; j++) {
if (grid[i][j] == 2) { //将所有腐烂的橘子放入队列中
q.push({i,j});
} else if (grid[i][j] == 1) {
fresh_cnt++;
}
}
}
int minutes = 0;
while (fresh_cnt > 0 && !q.empty()) { //注意:循环的条件里面需要加上fresh_cnt>0
// 对每一个腐烂的橘子进行一层一层腐烂扩散
int q_size = q.size();//当前扩散层所包含的烂橘子数
minutes++; //扩散次数加1
for (int k = 0; k < q_size; k++) { //从队列中弹出当前层的腐烂橘子,同时将当前层的邻居新鲜橘子扩散
const auto& vp = q.front(); //这里是引用,那么pop必须复制完i,j之后,否则会出现悬空引用的情况
int i = vp.first;
int j = vp.second;
q.pop();
if (i - 1 >= 0 && grid[i - 1][j] == 1) { //向上扩散
grid[i - 1][j] = 2; //对新鲜橘子进行腐烂处理
fresh_cnt--; //新鲜橘子个数少1
q.push({i - 1, j});
}
if (i + 1 < rnum && grid[i + 1][j] == 1) { //向下扩散
grid[i + 1][j] = 2;
fresh_cnt--;
q.push({i + 1, j});
}
if (j - 1 >= 0 && grid[i][j - 1] == 1) { //向左扩散
grid[i][j - 1] = 2;
fresh_cnt--;
q.push({i, j - 1});
}
if (j + 1 < cnum && grid[i][j + 1] == 1) { //向右扩散
grid[i][j + 1] = 2;
fresh_cnt--;
q.push({i, j + 1});
}
}
}
return fresh_cnt > 0 ? -1 : minutes; //判断最后是否还有新鲜橘子剩余
}
};