127. Word Ladder(Medium)
这道题有收货,想拿出来分享一下。
搜索题,开始用BFS,妥妥的超时,看到shortest 最短的搜索一定要先想到用BFS。
首先是单向的BFS,从beginWord开始每次把每个单词的所有字母替换,用visited做标记。
wordList = list(set(wordList))
queue = [(beginWord,1)]
visited = set()
while queue:
word,path = queue.pop(0)
if word == endWord:
return path
for i in range(len(word)):
for j in "abcdefghijklmnopqrstuvwxyz":
tmp = word[:i] + j + word[i+1:]
if tmp in wordList and tmp not in visited:
queue.append((tmp, path + 1))
visited.add(tmp)
return 0
然而 [Time Limit Exceeded]
看了解析后发现双向BFS才能过,原理如图。
巧妙之处在于单向BFS是自顶向下的,而双向的每次bfs查看front队列和back 谁小,相对于取上还是取下取决于遍历次数,数据量大可以减少很多次的遍历。
def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
if endWord not in wordList:
return 0
wordList = set(wordList)
front, back = set([beginWord]), set([endWord])
res = 1
#双向BFS
while front:
res += 1
tmp_queue = set()
for word in front:
for i in range(len(word)):
for c in "abcdefghijklmnopqrstuvwxyz":
if c != word[i]:
tmp = word[:i] + c + word[i+1:]
if tmp in back:
return res
if tmp in wordList: #注意set()的add与remove
tmp_queue.add(tmp)
wordList.remove(tmp)
front = tmp_queue
if len(front) > len(back): #关键点 减少bfs次数
front, back = back, front
return 0