Loading...https://leetcode.com/problems/word-ladder-ii/
这道题区别于127 Word Ladder 在于
1. 127 求的是最短路径长度;本题求的是最短路径
2. 127 求的是一个值,本题求的是所有的最短路径
为了解决这个变化,关键点是
1. 对于上一层之前访问的节点我们不能再访问了
2. 对于下一层要访问的节点,我们要记录所有的路径。
class Solution:
def findLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> List[List[str]]:
if endWord not in wordList:
return []
word_dict = set(wordList)
queue = collections.deque([beginWord])
# dict[word(str), paths(List[List[str]]): all paths from beginWord to endWord]
seen = {beginWord: [ [ beginWord ] ] }
while queue:
seen_in_this_level = {}
for _ in range(len(queue)):
word = queue.popleft()
if word == endWord:
return seen[word]
for next_word in self._get_next_words(word, word_dict):
if next_word in seen:
continue
# !! instead of adding next_word into 'seen'
# we add it into 'seen_in_this_level'
# because multiple words may have 'endWord' as the next word
#
# ted rex <-- current level
# \ /
# tex <-- next_word
#
# when word 'tex', next_word = 'tax', if we put 'tax' into 'seen',
# later when we visit word 'rex', we will skip 'tax', missing this valid path
if next_word not in seen_in_this_level:
seen_in_this_level[next_word] = []
paths = seen[word]
for path in paths:
new_path = path.copy()
new_path.append(next_word)
seen_in_this_level[next_word].append(new_path)
# !! de-dupe because we may see 'endWord' multiple times
queue = collections.deque(seen_in_this_level)
# !! add 'seen_in_this_level' to 'seen' only when the level is finished
seen.update(seen_in_this_level)
return []
def _get_next_words(self, word: str, word_dict: set[str]) -> set[str]:
next_words = set()
for i in range(len(word)):
ch = word[i]
left_substr, right_substr = word[: i], word[i + 1:]
for letter in "abcdefghijklmnopqrstuvwxyz":
new_word = left_substr + letter + right_substr
if new_word != word and new_word in word_dict:
next_words.add(new_word)
return next_words
和 126的解题对比