1
+ ///
2
+ /// Problem: Word Ladder II
3
+ ///
4
+ /// A transformation sequence from word beginWord to word endWord using a dictionary wordList is a
5
+ /// sequence of words beginWord -> s1 -> s2 -> ... -> sk such that:
6
+ ///
7
+ /// - Every adjacent pair of words differs by a single letter.
8
+ /// - Every si for 1 <= i <= k is in wordList. Note that beginWord does not need to be in wordList.
9
+ /// - sk == endWord
10
+ ///
11
+ /// Given two words, beginWord and endWord, and a dictionary wordList, return all the shortest
12
+ /// transformation sequences from beginWord to endWord, or an empty list if no such sequence exists.
13
+ /// Each sequence should be returned as a list of the words [beginWord, s1, s2, ..., sk].
14
+ ///
15
+ /// Example 1:
16
+ /// Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
17
+ /// Output: [["hit","hot","dot","dog","cog"],["hit","hot","lot","log","cog"]]
18
+ /// Explanation: There are 2 shortest transformation sequences:
19
+ /// "hit" -> "hot" -> "dot" -> "dog" -> "cog"
20
+ /// "hit" -> "hot" -> "lot" -> "log" -> "cog"
21
+ ///
22
+ /// Example 2:
23
+ /// Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
24
+ /// Output: []
25
+ /// Explanation: The endWord "cog" is not in wordList, so there is no valid transformation sequence.
26
+ ///
27
+ /// Constraints:
28
+ /// 1 <= beginWord.length <= 5
29
+ /// endWord.length == beginWord.length
30
+ /// 1 <= wordList.length <= 500
31
+ /// wordList[i].length == beginWord.length
32
+ /// beginWord, endWord, and wordList[i] consist of lowercase English letters.
33
+ /// beginWord != endWord
34
+ /// All the words in wordList are unique.
35
+ ///
36
+
37
+ // # Solution
38
+ // Time complexity: O(N * M^2) where N is the length of wordList and M is the length of each word
39
+ // Space complexity: O(N^2)
40
+
41
+ use std:: collections:: { HashSet , HashMap , VecDeque } ;
42
+ impl Solution {
43
+ pub fn find_ladders ( begin_word : String , end_word : String , word_list : Vec < String > ) -> Vec < Vec < String > > {
44
+ let mut word_set: HashSet < String > = word_list. into_iter ( ) . collect ( ) ;
45
+
46
+
47
+ if !word_set. contains ( & end_word) {
48
+ return vec ! [ ] ;
49
+ }
50
+
51
+ word_set. remove ( & begin_word) ;
52
+
53
+ let mut queue = VecDeque :: new ( ) ;
54
+ queue. push_back ( begin_word. clone ( ) ) ;
55
+
56
+ let mut parents: HashMap < String , Vec < String > > = HashMap :: new ( ) ;
57
+
58
+ let mut current_level = HashSet :: new ( ) ;
59
+ current_level. insert ( begin_word. clone ( ) ) ;
60
+
61
+ let mut found = false ;
62
+
63
+ while !queue. is_empty ( ) && !found {
64
+ let level_size = queue. len ( ) ;
65
+
66
+ let mut level_visited = HashSet :: new ( ) ;
67
+
68
+ for _ in 0 ..level_size {
69
+ let current_word = queue. pop_front ( ) . unwrap ( ) ;
70
+
71
+ let word_chars: Vec < char > = current_word. chars ( ) . collect ( ) ;
72
+
73
+ for i in 0 ..word_chars. len ( ) {
74
+ let mut new_chars = word_chars. clone ( ) ;
75
+
76
+ for c in b'a' ..=b'z' {
77
+ new_chars[ i] = c as char ;
78
+ let new_word: String = new_chars. iter ( ) . collect ( ) ;
79
+
80
+ if !word_set. contains ( & new_word) {
81
+ continue ;
82
+ }
83
+
84
+ parents. entry ( new_word. clone ( ) )
85
+ . or_insert_with ( Vec :: new)
86
+ . push ( current_word. clone ( ) ) ;
87
+
88
+ if !level_visited. contains ( & new_word) {
89
+ level_visited. insert ( new_word. clone ( ) ) ;
90
+
91
+ if new_word == end_word {
92
+ found = true ;
93
+ } else {
94
+ queue. push_back ( new_word) ;
95
+ }
96
+ }
97
+ }
98
+ }
99
+ }
100
+
101
+ for word in & level_visited {
102
+ word_set. remove ( word) ;
103
+ }
104
+ }
105
+
106
+ if !found {
107
+ return vec ! [ ] ;
108
+ }
109
+
110
+ let mut result = Vec :: new ( ) ;
111
+ let mut path = vec ! [ end_word. clone( ) ] ;
112
+
113
+ Self :: dfs ( & end_word, & begin_word, & parents, & mut path, & mut result) ;
114
+
115
+ result
116
+ }
117
+
118
+ fn dfs ( word : & str , begin_word : & str , parents : & HashMap < String , Vec < String > > ,
119
+ path : & mut Vec < String > , result : & mut Vec < Vec < String > > ) {
120
+ if word == begin_word {
121
+ let mut complete_path = path. clone ( ) ;
122
+ complete_path. reverse ( ) ;
123
+ result. push ( complete_path) ;
124
+ return ;
125
+ }
126
+
127
+ if let Some ( parent_words) = parents. get ( word) {
128
+ for parent in parent_words {
129
+ path. push ( parent. clone ( ) ) ;
130
+ Self :: dfs ( parent, begin_word, parents, path, result) ;
131
+ path. pop ( ) ;
132
+ }
133
+ }
134
+ }
135
+ }
0 commit comments