思路: 多源广度优先搜索
因为源头不是固定的,所以需要先将腐蚀源放到队列中,同时开始腐蚀。
//多源广度优先搜索
class Solution {
public int orangesRotting(int[][] grid) {
int m = grid.length, n = grid[0].length;
// 烂橘子坐标 是 bfs起点
Queue<int[]> queue = new LinkedList<>();
// 好橘子数量
int freshCount = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
// 烂橘子
if (grid[i][j] == 2) {
queue.offer(new int[]{i, j});// 烂橘子入队
} else if (grid[i][j] == 1) {
freshCount++; // 好橘子
}
}
}
int time = 0;
// bfs条件 1.有烂橘子 2.有好橘子
while (!queue.isEmpty() && freshCount > 0) {
int size = queue.size();
time++;
for(int i = 0; i < size; i++) {
int[] coord = queue.poll();
int row = coord[0], col = coord[1];
// 四个方向
if (col + 1 < n && grid[row][col + 1] == 1) {
queue.offer(new int[]{row, col + 1});
grid[row][col + 1] = 2;
freshCount--;
}
if (col - 1 >= 0 && grid[row][col - 1] == 1) {
queue.offer(new int[]{row, col - 1});
grid[row][col - 1] = 2;
freshCount--;
}
if (row + 1 < m && grid[row + 1][col] == 1) {
queue.offer(new int[]{row + 1, col});
grid[row + 1][col] = 2;
freshCount--;
}
if (row - 1 >= 0 && grid[row - 1][col] == 1) {
queue.offer(new int[]{row - 1, col});
grid[row - 1][col] = 2;
freshCount--;
}
}
}
// 如果还有好橘子,说明无法腐蚀到,return -1
return freshCount == 0 ? time : -1;
}
}
encode 坐标:
class Solution {
public int orangesRotting(int[][] grid) {
int m = grid.length, n = grid[0].length;
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 2) {
queue.offer(i * n + j);
//需要先把腐烂的全部加到队列中,多源广度优先搜索
//万一一开始有多个腐烂的,可以同时开始腐蚀,ex:[[2,1,1],[1,1,1],[0,1,2]]
//如果按一个开始腐蚀,时间可能不对。
}
}
}
int time = 0;
//hasFresh(grid)表示还有未被腐蚀的
//!queue.isEmpty()表示还有烂橘子没腐蚀周边
while (!queue.isEmpty() && hasFresh(grid)) {
int size = queue.size();
time++;
for (int k = 0; k < size; k++) {
int num = queue.poll();
int curi = num / n, curj = num % n;
if (curi + 1 < m && grid[curi + 1][curj] == 1) {
grid[curi + 1][curj] = 2;
queue.offer((curi + 1) * n + curj);
}
if (curi - 1 >= 0 && grid[curi - 1][curj] == 1) {
grid[curi - 1][curj] = 2;
queue.offer((curi - 1) * n + curj);
}
if (curj + 1 < n && grid[curi][curj + 1] == 1) {
grid[curi][curj + 1] = 2;
queue.offer(curi * n + curj + 1);
}
if (curj - 1 >= 0 && grid[curi][curj - 1] == 1) {
grid[curi][curj - 1] = 2;
queue.offer(curi * n + curj - 1);
}
}
}
//如果是腐蚀源执行完腐蚀操作,可能还有永远腐蚀不到的,这时候要返回-1
if (hasFresh(grid)) {
return -1;
}
return time;
}
//扫一遍,有新鲜橘子true, 无false
public boolean hasFresh(int[][] grid) {
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j] == 1) {
return true;
}
}
}
return false;
}
}