65
65
66
66
** 方法一:排序 + 前缀树**
67
67
68
+ 题目要求在输入 ` searchWord ` 的每一个字母后,推荐 ` products ` 数组中前缀与 ` searchWord ` 相同的最多三个产品。如果前缀相同的可推荐产品超过三个,按字典序返回最小的三个。
69
+
70
+ 找前缀相同的产品,可以使用前缀树;而要返回字典序最小的三个产品,我们可以先对 ` products ` 数组进行排序,然后将排序后的数组下标存入前缀树中。
71
+
72
+ 前缀树的每个节点维护以下信息:
73
+
74
+ - ` children ` :这是一个长度为 $26$ 的数组,用于存储当前节点的子节点,` children[i] ` 表示当前节点的子节点中字符为 ` i + 'a' ` 的节点。
75
+ - ` v ` :这是一个数组,用于存储当前节点的子节点中的字符在 ` products ` 数组中的下标,最多存储三个下标。
76
+
77
+ 搜索时,我们从前缀树的根节点开始,找到每一个前缀对应的下标数组,将其存入结果数组中。最后只需要将每个下标数组中的下标对应到 ` products ` 数组中即可。
78
+
79
+ 时间复杂度 $O(L \times \log n + m)$,空间复杂度 $O(L)$。其中 $L$ 是 ` products ` 数组所有字符串的长度之和,而 $n$ 和 $m$ 分别是 ` products ` 数组的长度和 ` searchWord ` 的长度。
80
+
68
81
<!-- tabs:start -->
69
82
70
83
### ** Python3**
74
87
``` python
75
88
class Trie :
76
89
def __init__ (self ):
77
- self .children = [None ] * 26
78
- self .v = []
90
+ self .children: List[Union[Trie, None ]] = [None ] * 26
91
+ self .v: List[ int ] = []
79
92
80
- def insert (self , word , i ):
93
+ def insert (self , w , i ):
81
94
node = self
82
- for c in word :
95
+ for c in w :
83
96
idx = ord (c) - ord (' a' )
84
97
if node.children[idx] is None :
85
98
node.children[idx] = Trie()
86
99
node = node.children[idx]
87
- node.v.append(i)
100
+ if len (node.v) < 3 :
101
+ node.v.append(i)
88
102
89
- def search (self , word ):
90
- res = [[] for _ in range (len (word))]
103
+ def search (self , w ):
91
104
node = self
92
- for i, c in enumerate (word):
105
+ ans = [[] for _ in range (len (w))]
106
+ for i, c in enumerate (w):
93
107
idx = ord (c) - ord (' a' )
94
108
if node.children[idx] is None :
95
109
break
96
110
node = node.children[idx]
97
- res [i] = node.v[: 3 ]
98
- return res
111
+ ans [i] = node.v
112
+ return ans
99
113
100
114
101
115
class Solution :
@@ -106,8 +120,7 @@ class Solution:
106
120
trie = Trie()
107
121
for i, w in enumerate (products):
108
122
trie.insert(w, i)
109
- res = trie.search(searchWord)
110
- return [[products[j] for j in v] for v in res]
123
+ return [[products[i] for i in v] for v in trie.search(searchWord)]
111
124
```
112
125
113
126
### ** Java**
@@ -119,37 +132,34 @@ class Trie {
119
132
Trie [] children = new Trie [26 ];
120
133
List<Integer > v = new ArrayList<> ();
121
134
122
- void insert (String word , int i ) {
135
+ public void insert (String w , int i ) {
123
136
Trie node = this ;
124
- for (char c : word . toCharArray() ) {
125
- c -= ' a' ;
126
- if (node. children[c ] == null ) {
127
- node. children[c ] = new Trie ();
137
+ for (int j = 0 ; j < w . length(); ++ j ) {
138
+ int idx = w . charAt(j) - ' a' ;
139
+ if (node. children[idx ] == null ) {
140
+ node. children[idx ] = new Trie ();
128
141
}
129
- node = node. children[c ];
142
+ node = node. children[idx ];
130
143
if (node. v. size() < 3 ) {
131
144
node. v. add(i);
132
145
}
133
146
}
134
147
}
135
148
136
- List<List<Integer > > search (String word ) {
137
- List<List<Integer > > res = new ArrayList<> ();
138
- int n = word. length();
139
- for (int i = 0 ; i < n; ++ i) {
140
- res. add(new ArrayList<> ());
141
- }
149
+ public List<Integer > [] search (String w ) {
142
150
Trie node = this ;
151
+ int n = w. length();
152
+ List<Integer > [] ans = new List [n];
153
+ Arrays . setAll(ans, k - > new ArrayList<> ());
143
154
for (int i = 0 ; i < n; ++ i) {
144
- char c = word. charAt(i);
145
- c -= ' a' ;
146
- if (node. children[c] == null ) {
155
+ int idx = w. charAt(i) - ' a' ;
156
+ if (node. children[idx] == null ) {
147
157
break ;
148
158
}
149
- node = node. children[c ];
150
- res . set(i, node. v) ;
159
+ node = node. children[idx ];
160
+ ans[i] = node. v;
151
161
}
152
- return res ;
162
+ return ans ;
153
163
}
154
164
}
155
165
@@ -160,9 +170,8 @@ class Solution {
160
170
for (int i = 0 ; i < products. length; ++ i) {
161
171
trie. insert(products[i], i);
162
172
}
163
- List<List<Integer > > res = trie. search(searchWord);
164
173
List<List<String > > ans = new ArrayList<> ();
165
- for (List< Integer > v : res ) {
174
+ for (var v : trie . search(searchWord) ) {
166
175
List<String > t = new ArrayList<> ();
167
176
for (int i : v) {
168
177
t. add(products[i]);
@@ -174,6 +183,66 @@ class Solution {
174
183
}
175
184
```
176
185
186
+ ### ** C++**
187
+
188
+ ``` cpp
189
+ class Trie {
190
+ public:
191
+ void insert(string& w, int i) {
192
+ Trie* node = this;
193
+ for (int j = 0; j < w.size(); ++j) {
194
+ int idx = w[ j] - 'a';
195
+ if (!node->children[ idx] ) {
196
+ node->children[ idx] = new Trie();
197
+ }
198
+ node = node->children[ idx] ;
199
+ if (node->v.size() < 3) {
200
+ node->v.push_back(i);
201
+ }
202
+ }
203
+ }
204
+
205
+ vector<vector<int>> search(string& w) {
206
+ Trie* node = this;
207
+ int n = w.size();
208
+ vector<vector<int>> ans(n);
209
+ for (int i = 0; i < w.size(); ++i) {
210
+ int idx = w[i] - 'a';
211
+ if (!node->children[idx]) {
212
+ break;
213
+ }
214
+ node = node->children[idx];
215
+ ans[i] = move(node->v);
216
+ }
217
+ return ans;
218
+ }
219
+
220
+ private:
221
+ vector<Trie*> children = vector<Trie*>(26 );
222
+ vector<int > v;
223
+ };
224
+
225
+ class Solution {
226
+ public:
227
+ vector<vector<string >> suggestedProducts(vector<string >& products, string searchWord) {
228
+ sort(products.begin(), products.end());
229
+ Trie* trie = new Trie();
230
+ for (int i = 0; i < products.size(); ++i) {
231
+ trie->insert(products[ i] , i);
232
+ }
233
+ vector<vector<string >> ans;
234
+ for (auto& v : trie->search(searchWord)) {
235
+ vector<string > t;
236
+ for (int i : v) {
237
+ t.push_back(products[ i] );
238
+ }
239
+ ans.push_back(move(t));
240
+ }
241
+ return ans;
242
+ }
243
+ };
244
+ ```
245
+
177
246
### **Go**
178
247
179
248
```go
@@ -185,9 +254,9 @@ type Trie struct {
185
254
func newTrie() *Trie {
186
255
return &Trie{}
187
256
}
188
- func (this *Trie ) insert (word string , i int ) {
257
+ func (this *Trie) insert(w string, i int) {
189
258
node := this
190
- for _ , c := range word {
259
+ for _, c := range w {
191
260
c -= 'a'
192
261
if node.children[c] == nil {
193
262
node.children[c] = newTrie()
@@ -199,37 +268,35 @@ func (this *Trie) insert(word string, i int) {
199
268
}
200
269
}
201
270
202
- func (this *Trie ) search (word string ) [][]int {
271
+ func (this *Trie) search(w string) [][]int {
203
272
node := this
204
- n := len (word )
205
- res := make ([][]int , n)
206
- for i , c := range word {
273
+ n := len(w )
274
+ ans := make([][]int, n)
275
+ for i, c := range w {
207
276
c -= 'a'
208
277
if node.children[c] == nil {
209
278
break
210
279
}
211
280
node = node.children[c]
212
- res [i] = node.v
281
+ ans [i] = node.v
213
282
}
214
- return res
283
+ return ans
215
284
}
216
285
217
- func suggestedProducts (products []string , searchWord string ) [][]string {
286
+ func suggestedProducts(products []string, searchWord string) (ans [][]string) {
218
287
sort.Strings(products)
219
288
trie := newTrie()
220
289
for i, w := range products {
221
290
trie.insert(w, i)
222
291
}
223
- res := trie.search (searchWord)
224
- var ans [][]string
225
- for _ , v := range res {
292
+ for _, v := range trie.search(searchWord) {
226
293
t := []string{}
227
294
for _, i := range v {
228
295
t = append(t, products[i])
229
296
}
230
297
ans = append(ans, t)
231
298
}
232
- return ans
299
+ return
233
300
}
234
301
```
235
302
0 commit comments