52.腐烂的橘子

94 阅读2分钟

题目链接

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

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

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

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

解法 bfs扩展

思路

我刚开始的想法是和岛屿数量一样,去给他沉没掉,结果发现并不行,如果存在多个腐烂的橘子,它的腐烂传递应该是相同开始的。

所以这就不能使用 dfs 去解答,但是扩展的思路可以借鉴,如果当前橘子是腐烂的,那么它的上下左右的新鲜橘子都会腐烂,就是相当于向四个方向扩展。

那么问题来了,如何去定义时间呢?就是队列的层数,每腐烂完一层,时间自增。

还有额外的问题:

  • 队列遍历完毕,如果还存在新鲜橘子,直接返回 -1
  • 全都是新鲜的橘子,要返回 0,说明结果要从 0 开始
  • 所有的橘子都腐烂完,返回 bfs 层数减一

代码

function orangesRotting(grid: number[][]): number {
    const m = grid.length;
    const n = grid[0].length;

    const queue = [];
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (grid[i][j] === 2) {
                queue.push([i, j]);
            }
        }
    }

    const setRotten = (r, c) => {
        if (r < 0 || c < 0 || r >= m || c >= n || grid[r][c] !== 1) return;
        grid[r][c] = 2;
        queue.push([r, c]);
    }

    let result = 0;
    while (queue.length) {
        result++;

        let size = queue.length;
        while (size--) {
            const [i, j] = queue.shift();
            setRotten(i + 1, j);
            setRotten(i - 1, j);
            setRotten(i, j + 1);
            setRotten(i, j - 1);
        }
    }

    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (grid[i][j] === 1) {
                return - 1;
            }
        }
    }
    if (result === 0) {
        return 0;
    }
    return result - 1;
};

时空复杂度

时间复杂度:O(mn)

空间复杂度:O(mn)