-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path126. 单词接龙 II
More file actions
100 lines (84 loc) · 3.8 KB
/
126. 单词接龙 II
File metadata and controls
100 lines (84 loc) · 3.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
from collections import defaultdict
from typing import List
from collections import deque
import string
class Solution:
def findLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> List[List[str]]:
# 先将 wordList 放到哈希表里,便于判断某个单词是否在 wordList 里
word_set = set(wordList)
res = []
if len(word_set) == 0 or endWord not in word_set:
return res
successors = defaultdict(set)
# 第 1 步:使用广度优先遍历得到后继结点列表 successors
# key:字符串,value:广度优先遍历过程中 key 的后继结点列表
found = self.__bidirectional_bfs(beginWord, endWord, word_set, successors)
if not found:
return res
# 第 2 步:基于后继结点列表 successors ,使用回溯算法得到所有最短路径列表
path = [beginWord]
self.__dfs(beginWord, endWord, successors, path, res)
return res
def __bidirectional_bfs(self, beginWord, endWord, word_set, successors):
visited = set()
visited.add(beginWord)
visited.add(endWord)
begin_visited = set()
begin_visited.add(beginWord)
end_visited = set()
end_visited.add(endWord)
found = False
forward = True
word_len = len(beginWord)
while begin_visited:
if len(begin_visited) > len(end_visited):
begin_visited, end_visited = end_visited, begin_visited
forward = not forward
next_level_visited = set()
for current_word in begin_visited:
word_list = list(current_word)
for j in range(word_len):
origin_char = word_list[j]
for k in string.ascii_lowercase:
word_list[j] = k
next_word = ''.join(word_list)
if next_word in word_set:
if next_word in end_visited:
found = True
# 在另一侧找到单词以后,还需把这一层关系添加到「后继结点列表」
self.__add_to_successors(successors, forward, current_word, next_word)
if next_word not in visited:
next_level_visited.add(next_word)
self.__add_to_successors(successors, forward, current_word, next_word)
word_list[j] = origin_char
begin_visited = next_level_visited
# 取两集合全部的元素(并集,等价于将 next_level_visited 里的所有元素添加到 visited 里)
visited |= next_level_visited
if found:
break
return found
def __add_to_successors(self, successors, forward, current_word, next_word):
if forward:
successors[current_word].add(next_word)
else:
successors[next_word].add(current_word)
def __dfs(self, beginWord, endWord, successors, path, res):
if beginWord == endWord:
res.append(path[:])
return
if beginWord not in successors:
return
successor_words = successors[beginWord]
for next_word in successor_words:
path.append(next_word)
self.__dfs(next_word, endWord, successors, path, res)
path.pop()
if __name__ == '__main__':
beginWord = "hit"
endWord = "cog"
wordList = ["hot", "dot", "dog", "lot", "log", "cog"]
solution = Solution()
res = solution.findLadders(beginWord, endWord, wordList)
print(res)
# 学习别人的方法
# 链接:https://leetcode-cn.com/problems/word-ladder-ii/solution/yan-du-you-xian-bian-li-shuang-xiang-yan-du-you--2/