遍历:BFS

BFS每次搜索的时候从所有的frontier开始扩展,并保留新的起点在frontier。BFS可以用从一点(或者多源)开始寻找最近的答案,或者无权有向图或者无向两点之间的最短距离

DFS与BFS的比较:

  • 在有一些问题中,BFS会比DFS更加高效。例如在社交网络想要寻找两个朋友的链接度,DFS可能会钻进死胡同去搜索另一个朋友所有的subtree再回头过来找与他们更亲近的朋友。

  • 在分布式算法中,BFS作为“多兵作战“的算法比DFS的“单打独斗“更合适。比如说在crawl网页的过程中,我们可以暂时把目前爬到的域名frontier存在硬盘或者缓存中,然后让多个线程从frontier中选取一个域名继续爬。

回看前面DFS里的迷宫题,我们用BFS可以这样求解。

queue = [enter]
paths = {enter: [enter]}
while queue:
    v = queue.pop(0)
    if v==exit: return path[v]
    for u in neighbors(p):
        if u in path: continue
        if wall(u, v): continue
        queue.append(u)
        paths[u] = paths[v] + [u]
return []

这里我们简单起见只返回了任一可行解。留意这里因为要记录最后可行解的路径,我们用paths: point -> path来保存在任一点到达这一点的路径,并代替了使用vis数组来判断是否已经访问了某一点。

你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 。每个拨轮可以自由旋转:例如把 '9' 变为 '0''0' 变为 '9' 。每次旋转都只能旋转一个拨轮的一位数字。

锁的初始数字为 '0000' ,一个代表四个拨轮的数字的字符串。

列表 deadends 包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。

字符串 target 代表可以解锁的数字,你需要给出解锁需要的最小旋转次数,如果无论如何不能解锁,返回 -1

示例 1:

节省空间的双源BFS

例题:撞球迷宫

和一般的迷宫不一样,如果我们在Tilt Maze里面从起点找终点,我们就加入状态来表示球的行进方向,而且要多一个状态来表示“静止”。下面BFS和DFS中,用0-3来表示四个方向,用4来表示静止状态。

Tilt Mazes

Last updated

Was this helpful?