|
1 | 1 | package Problem0127
|
2 | 2 |
|
3 | 3 | func ladderLength(beginWord string, endWord string, words []string) int {
|
| 4 | + dictMap := make(map[string]byte) |
4 | 5 |
|
5 |
| - // isTransedEndWord 用于在生成 trans 的过程中标记,存在 ->endWord 的转换关系 |
6 |
| - // 用于提前结束 |
7 |
| - isTransedEndWord := false |
8 |
| - // cnt 用于记录生成trans的迭代次数 |
9 |
| - // 其实也是最短路径的长度 |
10 |
| - res := 1 |
11 |
| - var bfs func([]string, []string) |
12 |
| - // 使用 bfs 方法,递归地生成 trans |
13 |
| - bfs = func(words, nodes []string) { |
14 |
| - res++ |
15 |
| - // words 中的 w |
16 |
| - // 与 nodes 中的 n ,可以实现 n->w 的转换, |
17 |
| - // 则,w 会被放入 newNodes |
18 |
| - // 否则,w 会被放入 newWords |
19 |
| - newWords := make([]string, 0, len(words)) |
20 |
| - newNodes := make([]string, 0, len(words)) |
21 |
| - for _, w := range words { |
22 |
| - isTransed := false |
23 |
| - for _, n := range nodes { |
24 |
| - if isTransable(n, w) { |
25 |
| - isTransed = true |
| 6 | + for i := 0; i < len(words); i++ { |
| 7 | + if _, ok := dictMap[words[i]]; !ok { |
| 8 | + dictMap[words[i]] = byte(1) |
| 9 | + } |
| 10 | + } |
26 | 11 |
|
27 |
| - } |
28 |
| - } |
| 12 | + var wq wordQueue |
| 13 | + dist := 2 |
29 | 14 |
|
30 |
| - if isTransed { |
31 |
| - if w == endWord { |
32 |
| - isTransedEndWord = true |
33 |
| - return |
34 |
| - } |
35 |
| - newNodes = append(newNodes, w) |
36 |
| - } else { |
37 |
| - newWords = append(newWords, w) |
| 15 | + addNextWords(beginWord, dictMap, &wq) |
| 16 | + for !wq.empty() { |
| 17 | + wqLen := wq.size() |
| 18 | + for i := 0; i < wqLen; i++ { |
| 19 | + word := wq.popNext() |
| 20 | + if word == endWord { |
| 21 | + return dist |
38 | 22 | }
|
39 |
| - } |
40 | 23 |
|
41 |
| - if len(newWords) == 0 || // words 的所有单词都已经可以从 beginWord trans 到 |
42 |
| - len(newNodes) == 0 { // newWords 中单词,是 beginWord 无法 trans 到的 |
43 |
| - return |
| 24 | + addNextWords(word, dictMap, &wq) |
44 | 25 | }
|
45 |
| - |
46 |
| - // 上面没有 return,要继续完善 trans |
47 |
| - bfs(newWords, newNodes) |
| 26 | + dist++ |
48 | 27 | }
|
49 | 28 |
|
50 |
| - // 第一代 nodes 含有且仅含有 beginWord |
51 |
| - nodes := []string{beginWord} |
52 |
| - bfs(words, nodes) |
| 29 | + return 0 |
| 30 | +} |
| 31 | + |
| 32 | +func addNextWords(beginWord string, dictMap map[string]byte, wq *wordQueue) { |
| 33 | + bytes := []byte(beginWord) |
| 34 | + delete(dictMap, beginWord) |
| 35 | + for i := 0; i < len(bytes); i++ { |
| 36 | + diffLetter := bytes[i] |
| 37 | + for j := 0; j < 26; j++ { |
| 38 | + b := 'a' + byte(j) |
| 39 | + if b == diffLetter { |
| 40 | + continue |
| 41 | + } |
53 | 42 |
|
54 |
| - if !isTransedEndWord { |
55 |
| - // beginWord 无法 trans 到 endWord |
56 |
| - return 0 |
| 43 | + bytes[i] = b |
| 44 | + if _, ok := dictMap[string(bytes)]; ok { |
| 45 | + wq.push(string(bytes)) |
| 46 | + delete(dictMap, string(bytes)) |
| 47 | + } |
| 48 | + } |
| 49 | + bytes[i] = diffLetter |
57 | 50 | }
|
| 51 | +} |
58 | 52 |
|
59 |
| - return res |
| 53 | +type wordQueue struct { |
| 54 | + words []string |
60 | 55 | }
|
61 | 56 |
|
62 |
| -func isTransable(a, b string) bool { |
63 |
| - if a == b { |
64 |
| - return false |
65 |
| - } |
66 |
| - // onceAgain == true 说明已经出现过不同的字符了 |
67 |
| - onceAgain := false |
68 |
| - for i := range a { |
69 |
| - if a[i] != b[i] { |
70 |
| - if onceAgain { |
71 |
| - return false |
72 |
| - } |
73 |
| - onceAgain = true |
74 |
| - } |
| 57 | +func (wq *wordQueue) empty() bool { |
| 58 | + return len(wq.words) == 0 |
| 59 | +} |
| 60 | + |
| 61 | +func (wq *wordQueue) popNext() string { |
| 62 | + if len(wq.words) == 0 { |
| 63 | + return "" |
75 | 64 | }
|
76 | 65 |
|
77 |
| - return true |
| 66 | + s := wq.words[0] |
| 67 | + wq.words = wq.words[1:] |
| 68 | + return s |
| 69 | +} |
| 70 | + |
| 71 | +func (wq *wordQueue) push(s string) { |
| 72 | + wq.words = append(wq.words, s) |
| 73 | +} |
| 74 | + |
| 75 | +func (wq *wordQueue) size() int { |
| 76 | + return len(wq.words) |
78 | 77 | }
|
0 commit comments