题目描述

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

值 0 代表空单元格;
值 1 代表新鲜橘子;
值 2 代表腐烂的橘子。
每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。

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

示例 1:
图片说明
输入:[[2,1,1],[1,1,0],[0,1,1]]
输出:4

示例 2:

输入:[[2,1,1],[0,1,1],[1,0,1]]
输出:-1
解释:左下角的橘子(第 2 行, 第 0 列)永远不会腐烂,因为腐烂只会发生在 4 个正向上。
示例 3:

输入:[[0,2]]
输出:0
解释:因为 0 分钟时已经没有新鲜橘子了,所以答案就是 0 。

提示:

1 <= grid.length <= 10
1 <= grid[0].length <= 10
grid[i][j] 仅为 0、1 或 2


解题思路

本题的主要思路是对整个网格进行一次BFS遍历。有点类似于树的BFS遍历路径。
初始情况下,我们把所有的腐烂橘子的位置和腐烂时间当一个元素,入队。然后每次出队一个元素,对这个元素代表腐烂橘子的位置进行上下左右的感染(注意判断上下左右是否越界),将感染成功的新腐烂橘子的位置和腐烂时间当一个元素,入队。
以队列为循环,一直到所有的元素出队。若最后网格中还有新鲜橘子,则不可能(返回-1)。


代码

class Solution:
    def orangesRotting(self, grid: List[List[int]]) -> int:
        #存储网格行列数,设置初始时间为零
        row, col, time = len(grid), len(grid[0]), 0
        #设置方位列表,分别代表上,下,左,右
        direction = [(1, 0), (-1, 0), (0, -1), (0, 1)]
        #初始一个队列,将腐烂的橘子位置和时间,入队
        RotQueue = []
        #遍历整个网格
        for i in range(row):
            for j in range(col):
                if(grid[i][j]==2):#所在网格为腐烂橘子
                    RotQueue.append((i, j, time))
        # if(not RotQueue):#若初始时间网格中没有腐烂橘子,直接返回不可能
        #     return -1#这句话多余了,忽略了还存在网格中都为空

        #BFS
        while(RotQueue):
            r, c, time = RotQueue.pop(0)#弹出队列中第一个腐烂橘子的位置和腐烂时间
            for dr, dc in direction:#上下左右进行遍历
                if(0<=r+dr<row and 0<=c+dc<col and grid[r+dr][c+dc] == 1):
                    grid[r+dr][c+dc] = 2
                    RotQueue.append((r+dr, c+dc, time+1))
        #如果BFS后,网格中还有新鲜的橘子,说明不可能
        for r in grid:
            if 1 in r:
                return -1
        return time