LeetCode 126. Word Ladder II 中文解释 Chinese Version
该题思路为bfs+dfs.
如BFS+DFS,有几个超时的坑所说, 要作两个优化:
得出如下代码:
import queue
class Solution:
def dfs(self, cur, path, endWord, words, res):
path.append(cur)
if cur == endWord:
r_path = path.copy()
r_path.reverse()
res.append(r_path)
path.pop()
return
for pred in words[cur][1]:
self.dfs(pred, path, endWord, words, res)
path.pop()
def bfs(self, start_set, words, dist, end_word, found):
if not start_set or found:
return
next_set = set()
for word in start_set:
if word == end_word:
found = True
return
# 枚举每个可能的邻近单词
for i in range(len(word)):
for j in range(ord('a'), ord('z')+1):
w = word[:i] + chr(j) + word[i+1:]
if w in words and dist+1 <= words[w][0]:
words[w][0] = dist+1
next_set.add(w)
words[w][1].append(word)
self.bfs(next_set, words, dist+1, end_word, found)
def findLadders(self, beginWord: str, endWord: str, wordList):
words = dict()
for word in wordList:
words[word] = [float("inf"), []] # dist, preds
words[beginWord] = [0, []]
if endWord not in words:
return []
self.bfs({
beginWord}, words, 0, endWord, False)
res = []
self.dfs(endWord, [], beginWord, words, res)
return res
这里有几个注意的点:
words记录的两个变量含义, 分别为从源节点出发的最短距离, 和最短路径的前驱节点.
words = dict()
for word in wordList:
words[word] = [float("inf"), []] # dist, preds
words[beginWord] = [0, []]
words[w][0]
只有两个可能的值, float("inf")
代表该节点还没被访问过, dist代表该节点的最短距离.
通过逐一变换单词中某个字母来枚举可能邻近的单词:
for i in range(len(word)):
for j in range(ord('a'), ord('z')+1):
w = word[:i] + chr(j) + word[i+1:]
判断是否标记最短距离的时候, 合并了两条逻辑.
if w in words and dist+1 <= words[w][0]:
words[w][0] = dist+1
next_set.add(w)
words[w][1].append(word)
如果w in words
, 我们能确定w与word之间有边, 此时有三种情况:
words[w][0]
为flaot("inf")
, 它一定没被访问过, 有dist+1 < words[w][0]
, 要标记最短距离, 并加入前驱节点words[w][0]
是最短距离, dist+1
不可能比它更小
words[w][0] = dist+1
和next_set.add(w)
操作无副作用, 为了代码简单, 与第一条并在一起写了)dist+1 > words[w][0]
, 不作任何操作.dist+1 <= words[w][0]
时, 都要加入前驱节点, 且加入next_set
, 下一轮bfs要遍历.(此处自行脑补三种情况的图)
最后dfs从终点遍历回起点, 遇到起点时加入结果集, 记得加入翻转的路径:
if cur == endWord:
r_path = path.copy()
r_path.reverse()
res.append(r_path)
path.pop()
return
本题考验在BFS中记录最短距离和最短路径前驱节点的操作.
然后是利用前驱节点, 从终点DFS回到起点的操作