跳到主要内容

994. 腐烂的橘子

题目描述​

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

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

每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。

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

示例 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

出处:LeetCode

解法一:广度优先搜索​

思路​

可以使用广度优先搜索来解决这个问题。首先遍历一遍网格,将所有腐烂的橘子加入队列。然后不断从队列中取出橘子,将其周围的新鲜橘子腐烂,并将腐烂的橘子加入队列,直到队列为空。

实现​

function orangesRotting(grid: number[][]): number {
const rows = grid.length;
const cols = grid[0].length;
const directions = [[0, 1], [0, -1], [1, 0], [-1, 0]];
const queue: number[][] = [];
let freshCount = 0;
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
if (grid[i][j] === 2) {
queue.push([i, j]);
} else if (grid[i][j] === 1) {
freshCount++;
}
}
}
let minutes = 0;
while (queue.length > 0) {
const size = queue.length;
let hasRotten = false;
for (let i = 0; i < size; i++) {
const [row, col] = queue.shift()!;
for (const [dx, dy] of directions) {
const newRow = row + dx;
const newCol = col + dy;
if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols && grid[newRow][newCol] === 1) {
grid[newRow][newCol] = 2;
queue.push([newRow, newCol]);
freshCount--;
hasRotten = true;
}
}
}
if (hasRotten) {
minutes++;
}
}
return freshCount === 0 ? minutes : -1;
}

复杂度分析​

  • 时间复杂度:O(mn)O(mn),其中 mm 和 nn 分别是网格的行数和列数。最坏情况下,所有的橘子都会腐烂,需要遍历整个网格。
  • 空间复杂度:O(mn)O(mn)。在最坏情况下,整个网格均为新鲜橘子,队列的大小会达到 m×nm \times n。