学习记录:js算法(九十六):腐烂的橘子

腐烂的橘子

在给定的 m x n 网格 grid 中,每个单元格可以有以下三个值之一:
值 0 代表空单元格;
值 1 代表新鲜橘子;
值 2 代表腐烂的橘子。
每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。
返回 直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -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

思路一

function orangesRotting(grid) {
    const m = grid.length;
    const n = grid[0].length;
    let freshOranges = 0;
    const queue = [];
    const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];

    // 初始化
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (grid[i][j] === 2) {
                queue.push([i, j]);
            } else if (grid[i][j] === 1) {
                freshOranges++;
            }
        }
    }

    let minutes = 0;

    while (queue.length > 0 && freshOranges > 0) {
        const size = queue.length;
        for (let i = 0; i < size; i++) {
            const [r, c] = queue.shift();
            for (const [dr, dc] of directions) {
                const nr = r + dr;
                const nc = c + dc;
                if (nr >= 0 && nr < m && nc >= 0 && nc < n && grid[nr][nc] === 1) {
                    grid[nr][nc] = 2; // 橘子腐烂
                    freshOranges--; // 新鲜橘子数量减少
                    queue.push([nr, nc]); // 加入队列
                }
            }
        }
        minutes++; // 时间增加
    }

    return freshOranges === 0 ? minutes : -1;
}

讲解
腐烂的橘子问题(Rotting Oranges)涉及到在一个给定的网格中,某些单元格包含新鲜橘子(值为 1),某些单元格包含腐烂的橘子(值为 2),还有些单元格为空(值为 0)。腐烂的橘子会传染给相邻(上下左右)的新鲜橘子,使得它们在一分钟后也腐烂。任务是计算直到所有新鲜橘子都腐烂所需的分钟数,如果不可能则返回 -1。

  1. 初始化:创建一个队列 queue,用于存储腐烂橘子的位置。同时,计算总共有多少新鲜橘子。
  2. 广度优先搜索(BFS):从所有初始的腐烂橘子开始,使用 BFS 遍历网格。将所有初始的腐烂橘子位置加入队列,并开始 BFS 过程。
  3. 传播腐烂:在每一轮 BFS 中,从队列中取出腐烂橘子的位置,检查其四个相邻的单元格。如果相邻单元格中有新鲜橘子(值为 1),则将其标记为腐烂(值改为 2),并加入队列中等待下一轮传染。
  4. 更新时间:每完成一轮 BFS,表示所有能够被感染的新鲜橘子都已经变为腐烂状态,这时将时间加一。
  5. 检查是否全部腐烂:在 BFS 结束后,检查是否有新鲜橘子仍然存在。如果有,说明有些橘子永远无法腐烂,返回 -1。如果没有,返回经过的时间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值