53
53
54
54
** 方法一:前缀树**
55
55
56
+ 我们定义一棵前缀树,前缀树每个节点有两个属性,一个是长度为 $26$ 的子节点数组 ` children ` ,另一个是是否为单词结尾的标记 ` isEnd ` 。
57
+
58
+ 我们遍历 ` words ` ,对于每个单词 ` w ` ,我们从根节点开始遍历,如果当前节点的子节点数组中没有 ` w ` 的第一个字符,我们就创建一个新的节点,然后继续遍历 ` w ` 的下一个字符,直到遍历完 ` w ` ,我们将当前节点的 ` isEnd ` 标记为 ` true ` 。
59
+
60
+ 接下来我们遍历 ` words ` ,对于每个单词 ` w ` ,我们从根节点开始遍历,如果当前节点的子节点数组的 ` isEnd ` 字段为 ` false ` ,说明 ` w ` 的某个前缀不在 ` words ` 中,我们返回 ` false ` 。否则继续遍历 ` w ` 的下一个字符,直到遍历完 ` w ` ,我们返回 ` true ` 。
61
+
62
+ 时间复杂度 $O(\sum_ {w \in words} |w|)$,空间复杂度 $O(\sum_ {w \in words} |w|)$。
63
+
56
64
<!-- tabs:start -->
57
65
58
66
### ** Python3**
61
69
62
70
``` python
63
71
class Trie :
72
+ __slots__ = [" children" , " is_end" ]
73
+
64
74
def __init__ (self ):
65
- self .children = [None ] * 26
66
- self .is_end = False
75
+ self .children: List[Trie | None ] = [None ] * 26
76
+ self .is_end: bool = False
67
77
68
- def insert (self , w ) :
78
+ def insert (self , w : str ) -> None :
69
79
node = self
70
80
for c in w:
71
81
idx = ord (c) - ord (" a" )
72
- if node.children[idx] is None :
82
+ if not node.children[idx]:
73
83
node.children[idx] = Trie()
74
84
node = node.children[idx]
75
85
node.is_end = True
76
86
77
- def search (self , w ) :
87
+ def search (self , w : str ) -> bool :
78
88
node = self
79
89
for c in w:
80
90
idx = ord (c) - ord (" a" )
@@ -91,9 +101,7 @@ class Solution:
91
101
trie.insert(w)
92
102
ans = " "
93
103
for w in words:
94
- if ans and (len (ans) > len (w) or (len (ans) == len (w) and ans < w)):
95
- continue
96
- if trie.search(w):
104
+ if (len (w) > len (ans) or len (w) == len (ans) and w < ans) and trie.search(w):
97
105
ans = w
98
106
return ans
99
107
```
@@ -104,26 +112,29 @@ class Solution:
104
112
105
113
``` java
106
114
class Trie {
107
- Trie [] children = new Trie [26 ];
108
- boolean isEnd;
115
+ private Trie [] children = new Trie [26 ];
116
+ private boolean isEnd;
117
+
118
+ public Trie () {
119
+ }
109
120
110
- void insert (String w ) {
121
+ public void insert (String w ) {
111
122
Trie node = this ;
112
123
for (char c : w. toCharArray()) {
113
- c -= ' a' ;
114
- if (node. children[c ] == null ) {
115
- node. children[c ] = new Trie ();
124
+ int idx = c - ' a' ;
125
+ if (node. children[idx ] == null ) {
126
+ node. children[idx ] = new Trie ();
116
127
}
117
- node = node. children[c ];
128
+ node = node. children[idx ];
118
129
}
119
130
node. isEnd = true ;
120
131
}
121
132
122
- boolean search (String w ) {
133
+ public boolean search (String w ) {
123
134
Trie node = this ;
124
135
for (char c : w. toCharArray()) {
125
- c -= ' a' ;
126
- node = node. children[c ];
136
+ int idx = c - ' a' ;
137
+ node = node. children[idx ];
127
138
if (! node. isEnd) {
128
139
return false ;
129
140
}
@@ -140,12 +151,8 @@ class Solution {
140
151
}
141
152
String ans = " " ;
142
153
for (String w : words) {
143
- if (! " " . equals(ans)
144
- && (ans. length() > w. length()
145
- || (ans. length() == w. length() && ans. compareTo(w) < 0 ))) {
146
- continue ;
147
- }
148
- if (trie. search(w)) {
154
+ if ((w. length() > ans. length() || (w. length() == ans. length() && w. compareTo(ans) < 0 ))
155
+ && trie. search(w)) {
149
156
ans = w;
150
157
}
151
158
}
@@ -159,30 +166,34 @@ class Solution {
159
166
``` cpp
160
167
class Trie {
161
168
private:
162
- vector< Trie* > children;
163
- bool isEnd;
169
+ Trie* children[ 26 ] ;
170
+ bool isEnd = false ;
164
171
165
172
public:
166
- Trie()
167
- : children(26)
168
- , isEnd(false) { }
173
+ Trie() {
174
+ fill(begin( children), end(children), nullptr);
175
+ }
169
176
170
- void insert(string word ) {
177
+ void insert(const string& w ) {
171
178
Trie* node = this;
172
- for (char c : word) {
173
- c -= 'a';
174
- if (!node->children[c]) node->children[c] = new Trie();
175
- node = node->children[c];
179
+ for (char c : w) {
180
+ int idx = c - 'a';
181
+ if (!node->children[idx]) {
182
+ node->children[idx] = new Trie();
183
+ }
184
+ node = node->children[idx];
176
185
}
177
186
node->isEnd = true ;
178
187
}
179
188
180
- bool search (string word ) {
189
+ bool search (const string& w ) {
181
190
Trie* node = this;
182
- for (char c : word) {
183
- c -= 'a';
184
- node = node->children[ c] ;
185
- if (!node->isEnd) return false;
191
+ for (char c : w) {
192
+ int idx = c - 'a';
193
+ node = node->children[ idx] ;
194
+ if (!node->isEnd) {
195
+ return false;
196
+ }
186
197
}
187
198
return true;
188
199
}
@@ -191,12 +202,15 @@ public:
191
202
class Solution {
192
203
public:
193
204
string longestWord(vector<string >& words) {
194
- Trie* trie = new Trie();
195
- for (auto w : words) trie->insert(w);
205
+ Trie trie;
206
+ for (const string& w : words) {
207
+ trie.insert(w);
208
+ }
196
209
string ans = "";
197
- for (auto w : words) {
198
- if (ans != "" && (ans.size() > w.size() || (ans.size() == w.size() && ans < w))) continue;
199
- if (trie->search(w)) ans = w;
210
+ for (const string& w : words) {
211
+ if ((w.size() > ans.size() || (w.size() == ans.size() && w < ans)) && trie.search(w)) {
212
+ ans = w;
213
+ }
200
214
}
201
215
return ans;
202
216
}
@@ -214,22 +228,24 @@ type Trie struct {
214
228
func newTrie() *Trie {
215
229
return &Trie{}
216
230
}
217
- func (this *Trie) insert(word string) {
218
- node := this
219
- for _, c := range word {
220
- c -= 'a'
221
- if node.children[c] == nil {
222
- node.children[c] = newTrie()
231
+
232
+ func (t *Trie) insert(w string) {
233
+ node := t
234
+ for _, c := range w {
235
+ idx := c - 'a'
236
+ if node.children[idx] == nil {
237
+ node.children[idx] = newTrie()
223
238
}
224
- node = node.children[c ]
239
+ node = node.children[idx ]
225
240
}
226
241
node.isEnd = true
227
242
}
228
- func (this *Trie) search(word string) bool {
229
- node := this
230
- for _, c := range word {
231
- c -= 'a'
232
- node = node.children[c]
243
+
244
+ func (t *Trie) search(w string) bool {
245
+ node := t
246
+ for _, c := range w {
247
+ idx := c - 'a'
248
+ node = node.children[idx]
233
249
if !node.isEnd {
234
250
return false
235
251
}
@@ -244,17 +260,170 @@ func longestWord(words []string) string {
244
260
}
245
261
ans := ""
246
262
for _, w := range words {
247
- if ans != "" && (len(ans) > len(w) || (len(ans) == len(w) && ans < w)) {
248
- continue
249
- }
250
- if trie.search(w) {
263
+ if (len(w) > len(ans) || (len(w) == len(ans) && w < ans)) && trie.search(w) {
251
264
ans = w
252
265
}
253
266
}
254
267
return ans
255
268
}
256
269
```
257
270
271
+ ### ** TypeScript**
272
+
273
+ ``` ts
274
+ class Trie {
275
+ private children: (Trie | null )[] = Array (26 ).fill (null );
276
+ private isEnd: boolean = false ;
277
+
278
+ insert(w : string ): void {
279
+ let node: Trie = this ;
280
+ for (const c of w ) {
281
+ const idx: number = c .charCodeAt (0 ) - ' a' .charCodeAt (0 );
282
+ if (! node .children [idx ]) {
283
+ node .children [idx ] = new Trie ();
284
+ }
285
+ node = node .children [idx ] as Trie ;
286
+ }
287
+ node .isEnd = true ;
288
+ }
289
+
290
+ search(w : string ): boolean {
291
+ let node: Trie = this ;
292
+ for (const c of w ) {
293
+ const idx: number = c .charCodeAt (0 ) - ' a' .charCodeAt (0 );
294
+ node = node .children [idx ] as Trie ;
295
+ if (! node .isEnd ) {
296
+ return false ;
297
+ }
298
+ }
299
+ return true ;
300
+ }
301
+ }
302
+
303
+ function longestWord(words : string []): string {
304
+ const trie: Trie = new Trie ();
305
+ for (const w of words ) {
306
+ trie .insert (w );
307
+ }
308
+ let ans: string = ' ' ;
309
+ for (const w of words ) {
310
+ if ((w .length > ans .length || (w .length === ans .length && w < ans )) && trie .search (w )) {
311
+ ans = w ;
312
+ }
313
+ }
314
+ return ans ;
315
+ }
316
+ ```
317
+
318
+ ### ** Rust**
319
+
320
+ ``` rust
321
+ struct Trie {
322
+ children : [Option <Box <Trie >>; 26 ],
323
+ is_end : bool ,
324
+ }
325
+
326
+ impl Trie {
327
+ fn new () -> Self {
328
+ Trie {
329
+ children : Default :: default (),
330
+ is_end : false ,
331
+ }
332
+ }
333
+
334
+ fn insert (& mut self , w : & str ) {
335
+ let mut node = self ;
336
+ for c in w . chars () {
337
+ let idx = (c as usize ) - ('a' as usize );
338
+ node = node . children[idx ]. get_or_insert_with (|| Box :: new (Trie :: new ()));
339
+ }
340
+ node . is_end = true ;
341
+ }
342
+
343
+ fn search (& self , w : & str ) -> bool {
344
+ let mut node = self ;
345
+ for c in w . chars () {
346
+ let idx = (c as usize ) - ('a' as usize );
347
+ if let Some (next_node ) = & node . children[idx ] {
348
+ node = next_node . as_ref ();
349
+ if ! node . is_end {
350
+ return false ;
351
+ }
352
+ }
353
+ }
354
+ true
355
+ }
356
+ }
357
+
358
+ impl Solution {
359
+ pub fn longest_word (words : Vec <String >) -> String {
360
+ let mut trie = Trie :: new ();
361
+ for w in & words {
362
+ trie . insert (w );
363
+ }
364
+ let mut ans = String :: new ();
365
+ for w in & words {
366
+ if (w . len () > ans . len () || (w . len () == ans . len () && w < & ans )) && trie . search (w ) {
367
+ ans = w . clone ();
368
+ }
369
+ }
370
+ ans
371
+ }
372
+ }
373
+ ```
374
+
375
+ ### ** C#**
376
+
377
+ ``` cs
378
+ public class Trie {
379
+ private Trie [] children = new Trie [26 ];
380
+ private bool isEnd ;
381
+
382
+ public Trie () { }
383
+
384
+ public void Insert (string w ) {
385
+ Trie node = this ;
386
+ foreach (char c in w .ToCharArray ()) {
387
+ int idx = c - 'a' ;
388
+ if (node .children [idx ] == null ) {
389
+ node .children [idx ] = new Trie ();
390
+ }
391
+ node = node .children [idx ];
392
+ }
393
+ node .isEnd = true ;
394
+ }
395
+
396
+ public bool Search (string w ) {
397
+ Trie node = this ;
398
+ foreach (char c in w .ToCharArray ()) {
399
+ int idx = c - 'a' ;
400
+ node = node .children [idx ];
401
+ if (! node .isEnd ) {
402
+ return false ;
403
+ }
404
+ }
405
+ return true ;
406
+ }
407
+ }
408
+
409
+ public class Solution {
410
+ public string LongestWord (string [] words ) {
411
+ Trie trie = new Trie ();
412
+ foreach (string w in words ) {
413
+ trie .Insert (w );
414
+ }
415
+
416
+ string ans = " " ;
417
+ foreach (string w in words ) {
418
+ if ((w .Length > ans .Length || (w .Length == ans .Length && string .Compare (w , ans ) < 0 )) && trie .Search (w )) {
419
+ ans = w ;
420
+ }
421
+ }
422
+ return ans ;
423
+ }
424
+ }
425
+ ```
426
+
258
427
### ** ...**
259
428
260
429
```
0 commit comments