Leetcode 126.单词接龙 II
1 题目描述(Leetcode题目链接)
给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则:
- 每次转换只能改变一个字母。
- 转换过程中的中间单词必须是字典中的单词。
说明:
- 如果不存在这样的转换序列,返回一个空列表。
- 所有单词具有相同的长度。
- 所有单词只由小写字母组成。
- 字典中不存在重复的单词。
- 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
输入:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
输出:
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
输入:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
输出: []
解释: endWord "cog" 不在字典中,所以不存在符合要求的转换序列。
2 题目链接
这个题目不难,但是很麻烦。思路也很直观,就是先广度优先搜索,构造出前驱子图,到最后对前驱子图进行深度优先搜索输出路径序列。更多有关图的内容。
class Solution:
def dfs(self, root, path):
if self.parent[root]:
for word in self.parent[root]:
self.dfs(word, path + [word])
else:
self.res.append(path[::-1])
def findLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> List[List[str]]:
self.res = []
self.parent = collections.defaultdict(set) # 前驱子图
self.parent[beginWord] = None
wordList = set(wordList)
queue = collections.deque([beginWord])
seen = set() # 访问过的单词
seen.add(beginWord)
next_level = set() # 下一层要判断的单词
length = len(beginWord)
tag = 0 # 用来判断何时退出深度优先搜索
while queue:
num = len(queue)
while num:
num -= 1
curr = queue.popleft()
curr_li = list(curr)
for i in range(length):
char = curr_li[i]
for j in string.ascii_lowercase:
curr_li[i] = j
word = "".join(curr_li)
if word not in seen and word in wordList:
self.parent[word].add(curr)
next_level.add(word)
if word == endWord:
tag = 1
curr_li[i] = char
if tag == 1:
break
seen |= next_level
queue.extend(list(next_level))
next_level.clear()
if self.parent[endWord]:
self.dfs(endWord, [endWord])
return self.res