@@ -52,27 +52,363 @@ trie.search("app"); // 返回 True
52
52
53
53
<p ><meta charset =" UTF-8 " />注意:本题与主站 208 题相同:<a href =" https://leetcode-cn.com/problems/implement-trie-prefix-tree/ " >https://leetcode-cn.com/problems/implement-trie-prefix-tree/</a >  ; </p >
54
54
55
-
56
55
## 解法
57
56
58
57
<!-- 这里可写通用的实现逻辑 -->
59
58
59
+ 前缀树每个节点包括两部分:
60
+
61
+ 1 . 指向子节点的指针数组 children,对于本题而言,数组长度为 26,即小写英文字母的数量。` children[0] ` 对应小写字母 a,...,` children[25] ` 对应小写字母 z。
62
+ 1 . 布尔字段 ` isEnd ` ,表示该节点是否为字符串的结尾。
63
+
64
+ ### 1. 插入字符串
65
+
66
+ 我们从字典树的根开始,插入字符串。对于当前字符对应的子节点,有两种情况:
67
+
68
+ - 子节点存在。沿着指针移动到子节点,继续处理下一个字符。
69
+ - 子节点不存在。创建一个新的子节点,记录在 ` children ` 数组的对应位置上,然后沿着指针移动到子节点,继续搜索下一个字符。
70
+
71
+ 重复以上步骤,直到处理字符串的最后一个字符,然后将当前节点标记为字符串的结尾。
72
+
73
+ ### 2. 查找前缀
74
+
75
+ 我们从字典树的根开始,查找前缀。对于当前字符对应的子节点,有两种情况:
76
+
77
+ - 子节点存在。沿着指针移动到子节点,继续搜索下一个字符。
78
+ - 子节点不存在。说明字典树中不包含该前缀,返回空指针。
79
+
80
+ 重复以上步骤,直到返回空指针或搜索完前缀的最后一个字符。
81
+
82
+ 若搜索到了前缀的末尾,就说明字典树中存在该前缀。此外,若前缀末尾对应节点的 ` isEnd ` 为真,则说明字典树中存在该字符串。
83
+
60
84
<!-- tabs:start -->
61
85
62
86
### ** Python3**
63
87
64
88
<!-- 这里可写当前语言的特殊实现逻辑 -->
65
89
66
90
``` python
91
+ class Trie :
92
+
93
+ def __init__ (self ):
94
+ self .children = [None ] * 26
95
+ self .is_end = False
67
96
97
+ def insert (self , word : str ) -> None :
98
+ node = self
99
+ for c in word:
100
+ idx = ord (c) - ord (' a' )
101
+ if node.children[idx] is None :
102
+ node.children[idx] = Trie()
103
+ node = node.children[idx]
104
+ node.is_end = True
105
+
106
+ def search (self , word : str ) -> bool :
107
+ node = self ._search_prefix(word)
108
+ return node is not None and node.is_end
109
+
110
+ def startsWith (self , prefix : str ) -> bool :
111
+ node = self ._search_prefix(prefix)
112
+ return node is not None
113
+
114
+ def _search_prefix (self , prefix : str ):
115
+ node = self
116
+ for c in prefix:
117
+ idx = ord (c) - ord (' a' )
118
+ if node.children[idx] is None :
119
+ return None
120
+ node = node.children[idx]
121
+ return node
122
+
123
+ # Your Trie object will be instantiated and called as such:
124
+ # obj = Trie()
125
+ # obj.insert(word)
126
+ # param_2 = obj.search(word)
127
+ # param_3 = obj.startsWith(prefix)
68
128
```
69
129
70
130
### ** Java**
71
131
72
132
<!-- 这里可写当前语言的特殊实现逻辑 -->
73
133
74
134
``` java
135
+ class Trie {
136
+ private Trie [] children;
137
+ private boolean isEnd;
138
+
139
+ public Trie () {
140
+ children = new Trie [26 ];
141
+ }
142
+
143
+ public void insert (String word ) {
144
+ Trie node = this ;
145
+ for (char c : word. toCharArray()) {
146
+ int idx = c - ' a' ;
147
+ if (node. children[idx] == null ) {
148
+ node. children[idx] = new Trie ();
149
+ }
150
+ node = node. children[idx];
151
+ }
152
+ node. isEnd = true ;
153
+ }
154
+
155
+ public boolean search (String word ) {
156
+ Trie node = searchPrefix(word);
157
+ return node != null && node. isEnd;
158
+ }
159
+
160
+ public boolean startsWith (String prefix ) {
161
+ Trie node = searchPrefix(prefix);
162
+ return node != null ;
163
+ }
164
+
165
+ private Trie searchPrefix (String s ) {
166
+ Trie node = this ;
167
+ for (char c : s. toCharArray()) {
168
+ int idx = c - ' a' ;
169
+ if (node. children[idx] == null ) {
170
+ return null ;
171
+ }
172
+ node = node. children[idx];
173
+ }
174
+ return node;
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Your Trie object will be instantiated and called as such:
180
+ * Trie obj = new Trie();
181
+ * obj.insert(word);
182
+ * boolean param_2 = obj.search(word);
183
+ * boolean param_3 = obj.startsWith(prefix);
184
+ */
185
+ ```
186
+
187
+ ### ** JavaScript**
188
+
189
+ ``` js
190
+ /**
191
+ * Initialize your data structure here.
192
+ */
193
+ var Trie = function () {
194
+ this .children = {};
195
+ };
196
+
197
+ /**
198
+ * Inserts a word into the trie.
199
+ * @param {string} word
200
+ * @return {void}
201
+ */
202
+ Trie .prototype .insert = function (word ) {
203
+ let node = this .children ;
204
+ for (let char of word) {
205
+ if (! node[char]) {
206
+ node[char] = {};
207
+ }
208
+ node = node[char];
209
+ }
210
+ node .isEnd = true ;
211
+ };
212
+
213
+ /**
214
+ * Returns if the word is in the trie.
215
+ * @param {string} word
216
+ * @return {boolean}
217
+ */
218
+ Trie .prototype .search = function (word ) {
219
+ let node = this .searchPrefix (word);
220
+ return node != undefined && node .isEnd != undefined ;
221
+ };
222
+
223
+ Trie .prototype .searchPrefix = function (prefix ) {
224
+ let node = this .children ;
225
+ for (let char of prefix) {
226
+ if (! node[char]) return false ;
227
+ node = node[char];
228
+ }
229
+ return node;
230
+ }
231
+
232
+ /**
233
+ * Returns if there is any word in the trie that starts with the given prefix.
234
+ * @param {string} prefix
235
+ * @return {boolean}
236
+ */
237
+ Trie .prototype .startsWith = function (prefix ) {
238
+ return this .searchPrefix (prefix);
239
+ };
240
+
241
+ /**
242
+ * Your Trie object will be instantiated and called as such:
243
+ * var obj = new Trie()
244
+ * obj.insert(word)
245
+ * var param_2 = obj.search(word)
246
+ * var param_3 = obj.startsWith(prefix)
247
+ */
248
+ ```
249
+
250
+ ### ** C++**
251
+
252
+ ``` cpp
253
+ class Trie {
254
+ private:
255
+ vector<Trie* > children;
256
+ bool isEnd;
257
+
258
+ Trie* searchPrefix(string s) {
259
+ Trie* node = this;
260
+ for (char c : s)
261
+ {
262
+ int idx = c - 'a';
263
+ if (!node->children[idx]) return nullptr;
264
+ node = node->children[idx];
265
+ }
266
+ return node;
267
+ }
268
+
269
+ public:
270
+ Trie () : children(26), isEnd(false) {}
271
+
272
+ void insert(string word) {
273
+ Trie* node = this;
274
+ for (char c : word)
275
+ {
276
+ int idx = c - 'a';
277
+ if (!node->children[ idx] ) node->children[ idx] = new Trie();
278
+ node = node->children[ idx] ;
279
+ }
280
+ node->isEnd = true;
281
+ }
282
+
283
+ bool search(string word) {
284
+ Trie* node = searchPrefix(word);
285
+ return node != nullptr && node->isEnd;
286
+ }
287
+
288
+ bool startsWith(string prefix) {
289
+ Trie* node = searchPrefix(prefix);
290
+ return node != nullptr;
291
+ }
292
+ };
293
+
294
+ /**
295
+ * Your Trie object will be instantiated and called as such:
296
+ * Trie* obj = new Trie();
297
+ * obj->insert(word);
298
+ * bool param_2 = obj->search(word);
299
+ * bool param_3 = obj->startsWith(prefix);
300
+ * /
301
+ ```
302
+
303
+ ### **Go**
304
+
305
+ ```go
306
+ type Trie struct {
307
+ children [26]*Trie
308
+ isEnd bool
309
+ }
310
+
311
+ func Constructor() Trie {
312
+ return Trie{}
313
+ }
314
+
315
+ func (this *Trie) Insert(word string) {
316
+ node := this
317
+ for _, c := range word {
318
+ idx := c - 'a'
319
+ if node.children[idx] == nil {
320
+ node.children[idx] = &Trie{}
321
+ }
322
+ node = node.children[idx]
323
+ }
324
+ node.isEnd = true
325
+ }
326
+
327
+ func (this *Trie) Search(word string) bool {
328
+ node := this.SearchPrefix(word)
329
+ return node != nil && node.isEnd
330
+ }
331
+
332
+ func (this *Trie) StartsWith(prefix string) bool {
333
+ node := this.SearchPrefix(prefix)
334
+ return node != nil
335
+ }
336
+
337
+ func (this *Trie) SearchPrefix(s string) *Trie {
338
+ node := this
339
+ for _, c := range s {
340
+ idx := c - 'a'
341
+ if node.children[idx] == nil {
342
+ return nil
343
+ }
344
+ node = node.children[idx]
345
+ }
346
+ return node
347
+ }
348
+
349
+ /**
350
+ * Your Trie object will be instantiated and called as such:
351
+ * obj := Constructor();
352
+ * obj.Insert(word);
353
+ * param_2 := obj.Search(word);
354
+ * param_3 := obj.StartsWith(prefix);
355
+ */
356
+ ```
357
+
358
+ ### ** C#**
359
+
360
+ ``` cs
361
+ public class Trie {
362
+ bool isEnd ;
363
+ Trie [] children = new Trie [26 ];
364
+
365
+ public Trie () {
366
+
367
+ }
368
+
369
+ public void Insert (string word ) {
370
+ Trie node = this ;
371
+ foreach (var c in word )
372
+ {
373
+ var idx = c - 'a' ;
374
+ node .children [idx ] ??= new Trie ();
375
+ node = node .children [idx ];
376
+ }
377
+ node .isEnd = true ;
378
+ }
379
+
380
+ public bool Search (string word ) {
381
+ Trie node = SearchPrefix (word );
382
+ return node != null && node .isEnd ;
383
+ }
384
+
385
+ public bool StartsWith (string prefix ) {
386
+ Trie node = SearchPrefix (prefix );
387
+ return node != null ;
388
+ }
389
+
390
+ private Trie SearchPrefix (string s ) {
391
+ Trie node = this ;
392
+ foreach (var c in s )
393
+ {
394
+ var idx = c - 'a' ;
395
+ if (node .children [idx ] == null )
396
+ {
397
+ return null ;
398
+ }
399
+ node = node .children [idx ];
400
+ }
401
+ return node ;
402
+ }
403
+ }
75
404
405
+ /**
406
+ * Your Trie object will be instantiated and called as such:
407
+ * Trie obj = new Trie();
408
+ * obj.Insert(word);
409
+ * bool param_2 = obj.Search(word);
410
+ * bool param_3 = obj.StartsWith(prefix);
411
+ */
76
412
```
77
413
78
414
### ** ...**
0 commit comments