Skip to content

Commit b79436b

Browse files
committed
add word-ladder
1 parent 52ba38a commit b79436b

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed

go/word-ladder.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package leetcode
2+
3+
var (
4+
llWordRelation WordRelation
5+
llVisited map[string]bool
6+
)
7+
8+
type WordRelation map[string][]string
9+
10+
func (wr WordRelation) AddRelate(word, relation string) {
11+
entry, ok := wr[word]
12+
if !ok {
13+
entry = make([]string, 0, 8)
14+
}
15+
entry = append(entry, relation)
16+
wr[word] = entry
17+
}
18+
19+
func (wr WordRelation) GetRelate(word string) ([]string, bool) {
20+
entry, ok := wr[word]
21+
22+
return entry, ok
23+
}
24+
25+
func isLadder(s1, s2 string) bool {
26+
diff := 0
27+
for i := 0; i < len(s1); i++ {
28+
if s1[i] != s2[i] {
29+
diff++
30+
}
31+
if diff > 1 {
32+
return false
33+
}
34+
}
35+
36+
return true
37+
}
38+
39+
func bfs(beginWord, endWord string, pendingWords []string, level int) int {
40+
// fmt.Printf("level %d, pending %v\n", level, pendingWords)
41+
if len(pendingWords) == 0 {
42+
return 0
43+
}
44+
newPendingWords := make([]string, 0, len(pendingWords))
45+
for i := 0; i < len(pendingWords); i++ {
46+
if pendingWords[i] == endWord {
47+
return level + 2
48+
}
49+
llVisited[pendingWords[i]] = true
50+
entries, ok := llWordRelation.GetRelate(pendingWords[i])
51+
if !ok {
52+
continue
53+
}
54+
for _, word := range entries {
55+
if llVisited[word] {
56+
continue
57+
}
58+
newPendingWords = append(newPendingWords, word)
59+
}
60+
}
61+
return bfs(beginWord, endWord, newPendingWords, level+1)
62+
}
63+
64+
func ladderLength(beginWord string, endWord string, wordList []string) int {
65+
llWordRelation = make(WordRelation)
66+
pendingWords := make([]string, 0, 8)
67+
endInWordList := false
68+
for i := 0; i < len(wordList); i++ {
69+
if wordList[i] == endWord {
70+
endInWordList = true
71+
}
72+
73+
for j := i + 1; j < len(wordList); j++ {
74+
if isLadder(wordList[i], wordList[j]) {
75+
llWordRelation.AddRelate(wordList[i], wordList[j])
76+
llWordRelation.AddRelate(wordList[j], wordList[i])
77+
}
78+
}
79+
if isLadder(beginWord, wordList[i]) {
80+
pendingWords = append(pendingWords, wordList[i])
81+
}
82+
}
83+
if !endInWordList {
84+
return 0
85+
}
86+
87+
llVisited = make(map[string]bool)
88+
89+
return bfs(beginWord, endWord, pendingWords, 0)
90+
}

go/word-ladder_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package leetcode
2+
3+
import "testing"
4+
5+
func TestLadderLength(t *testing.T) {
6+
tests := []struct {
7+
beginWord string
8+
endWord string
9+
words []string
10+
expect int
11+
}{
12+
{
13+
beginWord: "hit",
14+
endWord: "cog",
15+
words: []string{"hot", "dot", "dog", "lot", "log", "cog"},
16+
expect: 5,
17+
}, {
18+
beginWord: "hit",
19+
endWord: "cog",
20+
words: []string{"hot", "dot", "dog", "lot", "log"},
21+
expect: 0,
22+
}, {
23+
beginWord: "a",
24+
endWord: "c",
25+
words: []string{"a", "b", "c"},
26+
expect: 2,
27+
},
28+
}
29+
for i, item := range tests {
30+
actual := ladderLength(item.beginWord, item.endWord, item.words)
31+
if actual != item.expect {
32+
t.Fatalf("%d expect %d actual %d\n", i, item.expect, actual)
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)