跳到主要内容

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] 仅为 012

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