今天常规刷题,刷到一道搜索的题目,第一次用单向BFS过了,然后发现耗时是大佬们的10倍,看了下网上的题解,大概学习了一下双向BFS。
双向BFS的特点是,从起点和终点同时出发,交替搜索,如果在中间相遇了,意味着终点和起点之间存在路径。双向BFS一般情况下可以大大减少搜索范围(脑补一下正方形从左上和右下启动,均按圆弧状往外搜索,一旦两个圆弧相交,搜索结束,那么左下角和右上角有大量区域不需要搜索)。能用双向BFS也是有限制的,起点和终点的位置必须是已知的,不然没法从两头开始启动搜索,比如从起点出发去找目标所在位置,这种搜索没法用双向BFS解决。
在实现BFS时,大概思路是:
1,先用起点和终点建立两个长度为一的集合set1和set2
2,进入循环
3,选择长度最短的集合进行更新(这样尽可能让每次计算量最小),一般操作是if len(set1) > len(set2): set1, set2 = set2, set1,然后一直都是更新set1。建立一个set3,为空,遍历set1,如果元素的子元素的vis为False,加入到set3,vis置为True; 如果为True,且在set2中(也就是另一端已经搜索到了),停止搜索,返回相应结果;如果都不是,就跳过
4,set1 = set3
5,回到2
补充一句:双向BFS还可以当成DFS的预处理,比如有些题目需要用DFS去把可行的路径全输出,可以先用双向BFS去判断这个方向可不可行在进行DFS搜索,当然,可不可行的状态要记得存,减少双向BFS的重复计算。
Leetcode127 给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换过程中,每次只能改变单词的一个字母,且要保证改变后单词在给定的字典中。
题解:
import numpy as np
import collections
import heapq
class Solution(object):
def ladderLength(self, beginWord, endWord, wordList):
"""
:type beginWord: str
:type endWord: str
:type wordList: List[str]
:rtype: int
"""
Map = {}
flag = {}
wordSet = set(wordList)
if endWord not in wordSet:
return 0
for item in wordSet:
flag[item] = False
Queue_1 = set()
Queue_1.add(beginWord)
Queue_2 = set()
Queue_2.add(endWord)
flag[endWord] = True
ans = 2
while len(Queue_1) != 0:
if len(Queue_1) > len(Queue_2):
Queue_1, Queue_2 = Queue_2, Queue_1
next = []
for item in Queue_1:
for i in range(len(item)):
for j in range(26):
if item[i] == chr(ord('a')+j):
continue
word = item[0:i] + chr(ord('a')+j) + item[i+1:]
if word in wordSet:
if flag[word] == False:
next.append(word)
flag[word] = True
elif word in Queue_2:
return ans
Queue_1 = set(next)
ans += 1
return 0