我模仿leetcode中wordLadder问题的双向解决方案 Word Ladder - LeetCode
给出两个单词( beginWord 和 endWord ),以及字典的单词列表,找到从 beginWord 到的最短转换序列的长度。 em> endWord ,例如:
- 一次只能更改一个字母。
- 每个转换的单词都必须存在于单词列表中。请注意, beginWord 不是 转换后的单词。
注意:
- 如果没有这样的转换序列,则返回0。
- 所有单词的长度相同。
- 所有单词仅包含小写字母字符。
- 您可以假定单词列表中没有重复项。
- 您可能认为 beginWord 和 endWord 是非空的并且不相同。
示例1:
Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"] Output: 5 Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", return its length 5.
示例2:
Input: beginWord = "hit" endWord = "cog" wordList = ["hot","dot","dog","lot","log"] Output: 0 Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
解决方案
class Solution2(object):
def ladderLength(self, beginWord, endWord, wordList):
#base case
if (endWord not in wordList) or (not endWord) or (not beginWord) or (not wordList):
return 0
size = len(beginWord)
word_set = set(wordList)
forwards, backwards = {beginWord}, {endWord}
visited = set()
step = 0
while forwards and backwards:
step += 1 #treat the first word as step 1
if len(forwards) > len(backwards):
forwards, backwards = backwards, forwards #switch process
#logging.debug(f"step: {step}, forwards: {forwards}, backwords: {backwards}")
neighbors= set()
for word in forwards:#visit words on this level
if word in visited: continue
for i in range(size):
for c in 'abcdefghijklmnopqrstuvwxyz':
next_word = word[:i] + c + word[i+1:]
if next_word in backwards: return step + 1 #terminating case
if next_word in word_set: neighbors.add(next_word)
#logging.debug(f"next_word{next_word}, step: {step}")
visited.add(word) #add visited word as the final step
forwards = neighbors
#logging.debug(f"final: {step}")
return 0
切换过程参考
if len(forwards) > len(backwards):
forwards, backwards = backwards, forwards #switch process
此解决方案简洁但不直观,我尝试将其更改为
if len(forwards) <= len(backward): current = forwards
else: current = backwards
neighbors = set()
for word in current:
.......
很遗憾,最后一步forwards = neighbors
无法正确处理。
如何解决问题
答案 0 :(得分:1)
这称为bidirectional search算法。此解决方案中的forward
和backward
是一种two-pointer
的想法,请始终选择较大的集合来进行BFS。它有助于更快地找到路径。
关于您要使用current
而不是切换forward
和backward
的问题,我认为这是不可能的。原因是,我们在逻辑中同时使用了forward
和backward
,因此在current
之外,您还应该提供类似another
的变量。但是current
和another
与forward
和backward
相同,因此您的想法行不通。
我认为该two-pointer
版本足够优雅简洁,我个人喜欢它。
我想出另一种方法,使用current index
接近您的想法:
class Solution:
def ladderLength(self, beginWord, endWord, wordList):
#base case
if (endWord not in wordList) or (not endWord) or (not beginWord) or (not wordList):
return 0
size = len(beginWord)
word_set = set(wordList)
entries = [{beginWord}, {endWord}]
visited = set()
step = 0
cur = 0
while entries[cur] and entries[1-cur]:
step += 1 #treat the first word as step 1
if entries[1-cur] > entries[cur]: #switch process
cur ^= 1
neighbors= set()
for word in entries[cur]:#visit words on this level
if word in visited: continue
for i in range(size):
for c in 'abcdefghijklmnopqrstuvwxyz':
next_word = word[:i] + c + word[i+1:]
if next_word in entries[1-cur]: return step + 1 #terminating case
if next_word in word_set: neighbors.add(next_word)
visited.add(word) #add visited word as the final step
entries[cur] = neighbors
return 0
希望对您有所帮助,如果还有其他问题,请发表评论。 :)