-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathfindLadders.go
More file actions
150 lines (130 loc) · 3.51 KB
/
Copy pathfindLadders.go
File metadata and controls
150 lines (130 loc) · 3.51 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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/* https://leetcode.com/problems/word-ladder-ii/
Given two words (beginWord and endWord), and a dictionary's word list,
find all shortest transformation sequence(s) from beginWord to endWord,
such that:
Only one letter can be changed at a time
Each transformed word must exist in the word list.
Note that beginWord is not a transformed word.
Note:
Return an empty list if there is no such transformation sequence.
All words have the same length.
All words contain only lowercase alphabetic characters.
You may assume no duplicates in the word list.
You may assume beginWord and endWord are non-empty and are not the same.
Example 1:
Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
Output:
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
Example 2:
Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
Output: []
Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
*/
package lbacktracking
func findLadders(beginWord string, endWord string, wordList []string) [][]string {
canTrans := func(word1, word2 string) bool {
// word1和word2是否可以相互转换
cnt := 0
for i := 0; i < len(word1) && cnt < 2; i++ {
if word1[i] != word2[i] {
cnt++
}
}
return cnt == 1
}
// 处理beginWord,endWord不在队列的情况
beginWordIdx, endWordEIdx := -1, -1
for i, word := range wordList {
if word == endWord {
endWordEIdx = i
} else if word == beginWord {
beginWordIdx = i
}
}
if endWordEIdx == -1 {
return [][]string{}
}
if beginWordIdx == -1 {
beginWordIdx = len(wordList)
wordList = append(wordList, beginWord)
}
// 缓存每个单词的候选词
relations := make(map[int]map[int]bool, len(wordList))
for i := 0; i < len(wordList); i++ {
relations[i] = map[int]bool{}
}
for i, word := range wordList {
for j := i + 1; j < len(wordList); j++ {
if canTrans(word, wordList[j]) {
relations[i][j], relations[j][i] = true, true
}
}
}
type Node struct {
value string
height int
preNodes map[*Node]bool
}
allNodes := make(map[int]*Node, len(wordList)+1)
for i, word := range wordList {
allNodes[i] = &Node{value: word, height: len(wordList), preNodes: map[*Node]bool{}}
}
allNodes[beginWordIdx].height = 0
// bfs层序处理关系
worked, curWords := map[*Node]bool{}, []int{beginWordIdx}
for len(curWords) != 0 {
nextWords := []int{}
for _, curWord := range curWords {
curNode := allNodes[curWord]
if curNode.value == endWord {
break
}
worked[curNode] = true
for nextWord := range relations[curWord] {
nextNode := allNodes[nextWord]
if _, ok := worked[nextNode]; ok {
continue
}
nextWords = append(nextWords, nextWord)
if tmp := curNode.height + 1; nextNode.height >= tmp {
nextNode.height = tmp
nextNode.preNodes[curNode] = true
}
}
}
curWords = nextWords
}
var dfs func(node *Node) [][]string
dfs = func(node *Node) [][]string {
if node == allNodes[beginWordIdx] {
return [][]string{{beginWord}}
}
res := [][]string{}
for nextNode := range node.preNodes {
if nextNode.height == node.height-1 {
subs := dfs(nextNode)
for _, sub := range subs {
tmp := append([]string{node.value}, sub...)
res = append(res, tmp)
}
}
}
return res
}
res := dfs(allNodes[endWordEIdx])
for i := range res {
for j := 0; j < len(res[i])/2; j++ {
res[i][j], res[i][len(res[i])-1-j] = res[i][len(res[i])-1-j], res[i][j]
}
}
return res
}