来自Leetcode第994题腐烂的橘子
在给定的网格中,每个单元格可以有以下三个值之一:
- 值
0
代表空单元格;
- 值
1
代表新鲜橘子;
- 值
2
代表腐烂的橘子。
每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。
返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1
。
示例 1:
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 { 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(); 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); }
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;
} }
|
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; }
}
|