广度优先搜索算法(Breadth First Search,BFS)
更多请查看我的专栏:LeetCode(力扣)刷题指南
可直接在
LeetCode
中搜索题目名称
文章目录
1. 腐烂的橘子
在给定的网格中,每个单元格可以有以下三个值之一:
- 值
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
1.1 解决方案
1.方法一:枚举+广度优先搜索
每分钟每个腐烂的橘子都会使上下左右相邻的新鲜橘子腐烂——这是一个模拟广度优先搜索的过程。
所谓广度优先搜索,就是从起点出发,每次都尝试访问同一层的节点,如果同一层都访问完了,再访问下一层,最后广度优先搜索找到的路径就是从起点开始的最短合法路径。
假设图中只有一个腐烂的橘子,它每分钟向外拓展,腐烂上下左右相邻的新鲜橘子,那么下一分钟,就是这些被腐烂的橘子再向外拓展,进一步腐烂相邻的新鲜橘子,这与广度优先搜索的过程均一一对应
上下左右相邻的新鲜橘子就是该腐烂橘子尝试访问的同一层的节点,路径长度就是新鲜橘子被腐烂的时间。
#对上图例子拟建一个树,实现BFS算法
min 0 @
/ \
min 1 @ @
\ / \
min 2 @ @
/
min 3 @
\
min 4 @
我们记录下每个新鲜橘子被腐烂的时间,最后如果单元格中没有新鲜橘子,腐烂所有新鲜橘子所必须经过的最小分钟数就是新鲜橘子被腐烂的时间的最大值。
以上是基于图中只有一个腐烂的橘子的情况,可实际题目中腐烂的橘子数不止一个,看似与广度优先搜索有所区别,不能直接套用,但其实有两个方向的思路。
一个是耗时比较大且不推荐的做法:
我们对每个腐烂橘子为起点都进行一次广度优先搜索,用 dis[x][y][i] 表示只考虑第 i 个腐烂橘子为起点的广度优先搜索,坐标位于 (x, y) 的新鲜橘子被腐烂的时间,设没有被腐烂的新鲜橘子的 dis[x][y][i]=inf ,即无限大,表示没有被腐烂,那么每个新鲜橘子被腐烂的最短时间即为
min i d i s [ x ] [ y ] [ i ] \min_{i} dis[x][y][i] imin