Nameless Site

But one day, you will stand before its decrepit gate,without really knowing why.

0%

腐烂的橘子

来自Leetcode第994题腐烂的橘子

在给定的网格中,每个单元格可以有以下三个值之一:

  • 0 代表空单元格;
  • 1 代表新鲜橘子;
  • 2 代表腐烂的橘子。

每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。

返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1

示例 1:

img

1
2
输入:[[2,1,1],[1,1,0],[0,1,1]]
输出:4

BFS I

来自官方题解

观察到对于所有的腐烂橘子,其实它们在广度优先搜索上是等价于同一层的节点的

假设这些腐烂橘子刚开始是新鲜的,而有一个腐烂橘子(我们令其为超级源点)会在下一秒把这些橘子都变腐烂,而这个腐烂橘子刚开始在的时间是 -1−1 ,那么按照广度优先搜索的算法,下一分钟也就是第 00 分钟的时候,这个腐烂橘子会把它们都变成腐烂橘子,然后继续向外拓展,所以其实这些腐烂橘子是同一层的节点。那么在广度优先搜索的时候,我们将这些腐烂橘子都放进队列里进行广度优先搜索即可,最后每个新鲜橘子被腐烂的最短时间 dis[x][y]dis[x][y] 其实是以这个超级源点的腐烂橘子为起点的广度优先搜索得到的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Solution {
// dr,dc 配合使用得到 grid[r][c] 上grid[r-1][c]左grid[r][c-1]下grid[r+1][c]右grid[r][c+1]的元素
int[] dr = new int[]{-1, 0, 1, 0};
int[] dc = new int[]{0, -1, 0, 1};

public int orangesRotting(int[][] grid) {
// 获取二维数组的行数row 和 列数 column
int R = grid.length, C = grid[0].length;

// queue : all starting cells with rotten oranges
Queue<Integer> queue = new ArrayDeque();
Map<Integer, Integer> depth = new HashMap();
for (int r = 0; r < R; ++r)
for (int c = 0; c < C; ++c)
if (grid[r][c] == 2) {
int code = r * C + c; // 转化为索引唯一的一维数组
queue.add(code); //存储腐烂橘子
depth.put(code, 0); //存储橘子变为腐烂时的时间,key为橘子的一维数组下标,value为变腐烂的时间
}

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);
// 计次的关键 元素 grid[r][c] 的上左下右元素得腐烂时间应该一致
depth.put(ncode, depth.get(code) + 1);
ans = depth.get(ncode);
}
}
}

//检查grid,此时的grid能被感染已经都腐烂了,此时还新鲜的橘子无法被感染
for (int[] row: grid)
for (int v: row)
if (v == 1)
return -1;
return ans;

}
}

BFS II

首先遍历一遍数组,将腐烂橘子入队列,新鲜橘子计数;接下来开始计时,从-1时刻开始遍历队列,将腐烂橘子出队,判断周围是否会有新鲜的橘子,如果有就入队,并且计时+1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Solution {
public int orangesRotting(int[][] grid) {
Queue<int[]> queue = new LinkedList<>();
int e = 0;
for (int i = 0; i < grid.length; i++)
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j] == 2)
queue.offer(new int[]{i, j});
else if (grid[i][j] == 1)
e++;
}
if (queue.isEmpty() && e > 0)
return -1;
if (queue.isEmpty() && e == 0)
return 0;
int count = -1;
int[][] dis = new int[][]{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
while (!queue.isEmpty()) {

int size = queue.size();
for (int j = 0; j < size; j++) {

int[] p = queue.poll();
for (int i = 0; i < 4; i++) {
int nx = p[0] + dis[i][0], ny = p[1] + dis[i][1];
if (check(grid, nx, ny)) {
queue.offer(new int[]{nx, ny});
grid[nx][ny] = 2;
e--;
}
}
}
count++;
}
return e == 0 ? count : -1;
}
public boolean check(int[][] grid, int x, int y) {

return x < grid.length && x >= 0 && y < grid[0].length && y >= 0 && grid[x][y] == 1;
}

}