994.腐烂的橘子
在给定的 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.lengthn == grid[i].length1 <= m, n <= 10grid[i][j]仅为0、1或2
题解:
class Solution {
public int orangesRotting(int[][] grid) {
int[] direcrow = {-1, 0, 1, 0};
int[] direccol = {0, -1, 0, 1};
// 保存所有烂橘子的坐标到queue中
Queue<Integer> queue = new ArrayDeque<>();
// 保存橘子腐烂的时间
Map<Integer, Integer> map = new HashMap();
int R = grid.length;
int C = grid[0].length;
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
if (grid[i][j] == 2) {
// 按照行优先保存坐标
int dir = i * C + j;
queue.add(dir);
// 初始化一开始就有的烂橘子时间
map.put(dir, 0);
}
}
}
int minute = 0;
// 一直循环知道取出所有的烂橘子
while (!queue.isEmpty()) {
int dir = queue.remove();
// 将取出的坐标转换成对应的行和列
int i = dir / C;
int j = dir % C;
// 开始往四个方向感染
for (int k = 0; k < 4; k++) {
int newr = i + direcrow[k];
int newc = j + direccol[k];
if (newr >= 0 && newr < R && newc >= 0 && newc < C && grid[newr][newc] == 1) {
grid[newr][newc] = 2;
int newDir = newr * C + newc;
queue.add(newDir);
map.put(newDir, map.get(dir) + 1);
minute = map.get(newDir);
}
}
}
for (int[] r : grid) {
for (int c : r) {
if (c == 1) {
return -1;
}
}
}
return minute;
}
}
/**
0:空单元格
1:新鲜橘子
2:腐烂橘子
*/
// class Solution {
// // 横方向
// int[] dr = new int[]{-1, 0, 1, 0};
// // 纵方向
// int[] dc = new int[]{0, -1, 0, 1};
// public int orangesRotting(int[][] grid) {
// int R = grid.length, C = grid[0].length;
// Queue<Integer> queue = new ArrayDeque<Integer>();
// Map<Integer, Integer> depth = new HashMap<Integer, Integer>();
// for (int r = 0; r < R; ++r) {
// for (int c = 0; c < C; ++c) {
// if (grid[r][c] == 2) {
// /**
// 将烂橘子所在的位置按照列行先存储保存起来
// 行优先存储:
// 例如二维数组A[3][4],烂橘子所在位置A[2][3],按照行优先
// 所以就是i * n + j即2 * 4 + 3
// 如下就是r * C + c
// */
// int code = r * C + c;
// // 将每一行烂橘子位置按照行优先算出的位置记录进队列中
// queue.add(code);
// // map存储橘子变为腐烂时的时间,key为橘子的一维数组下标(行优先变的),value为变腐烂的时间
// depth.put(code, 0);
// }
// }
// }
// int ans = 0;
// // 当队列里还有烂橘子时
// while (!queue.isEmpty()) {
// // 取出队列中的烂橘子
// int code = queue.remove();
// // 将行优先算出的坐标位置还原成具体的哪一行哪一列
// int r = code / C, c = code % C;
// // 烂橘子开始往四个方向感染
// for (int k = 0; k < 4; ++k) {
// int nr = r + dr[k];
// int nc = c + dc[k];
// // 为了防止烂橘子在矩阵的边上进行计算的时候导致溢出,需要对边界进行判断
// // 同时判断烂橘子的四个方向上是不是新鲜橘子
// if (0 <= nr && nr < R && 0 <= nc && nc < C && grid[nr][nc] == 1) {
// // 把新鲜橘子感染
// grid[nr][nc] = 2;
// // 同样的通过行优先保存被感染的橘子坐标,并放入队列中
// int ncode = nr * C + nc;
// queue.add(ncode);
// // 腐烂橘子上下左右新鲜橘子被腐烂的时间应该是一致的
// depth.put(ncode, depth.get(code) + 1);
// ans = depth.get(ncode);
// }
// }
// }
// for (int[] row: grid) {
// for (int v: row) {
// if (v == 1) {
// return -1;
// }
// }
// }
// return ans;
// }
// }