@@ -68,7 +68,19 @@ fileSystem.get("/c"); // 返回 -1 因为该路径不存在。
68
68
69
69
** 方法一:前缀树**
70
70
71
- 哈希表实现前缀树。
71
+ 我们可以使用前缀树来存储路径,每个节点存储一个值,表示该节点对应的路径的值。
72
+
73
+ 定义前缀树的节点结构如下:
74
+
75
+ - ` children ` :子节点,使用哈希表存储,键为子节点的路径,值为子节点的引用;
76
+ - ` v ` :当前节点对应的路径的值。
77
+
78
+ 定义前缀树的方法如下:
79
+
80
+ - ` insert(w, v) ` :插入路径 $w$,并将其对应的值设为 $v$。如果路径 $w$ 已经存在或其父路径不存在,则返回 ` false ` ,否则返回 ` true ` 。时间复杂度为 $O(|w|)$,其中 $|w|$ 为路径 $w$ 的长度;
81
+ - ` search(w) ` :返回路径 $w$ 对应的值。如果路径 $w$ 不存在,则返回 $-1$。时间复杂度为 $O(|w|)$。
82
+
83
+ 总时间复杂度 $O(\sum_ {w \in W}|w|)$,总空间复杂度 $O(\sum_ {w \in W}|w|)$,其中 $W$ 为所有插入的路径的集合。
72
84
73
85
<!-- tabs:start -->
74
86
@@ -78,31 +90,29 @@ fileSystem.get("/c"); // 返回 -1 因为该路径不存在。
78
90
79
91
``` python
80
92
class Trie :
81
- def __init__ (self ):
93
+ def __init__ (self , v : int = - 1 ):
82
94
self .children = {}
83
- self .v = 0
95
+ self .v = v
84
96
85
- def insert (self , w , v ) :
97
+ def insert (self , w : str , v : int ) -> bool :
86
98
node = self
87
- ps = w.split(' / ' )
99
+ ps = w.split(" / " )
88
100
for p in ps[1 :- 1 ]:
89
101
if p not in node.children:
90
102
return False
91
103
node = node.children[p]
92
104
if ps[- 1 ] in node.children:
93
105
return False
94
- node.children[ps[- 1 ]] = Trie()
95
- node = node.children[ps[- 1 ]]
96
- node.v = v
106
+ node.children[ps[- 1 ]] = Trie(v)
97
107
return True
98
108
99
- def search (self , w ) :
109
+ def search (self , w : str ) -> int :
100
110
node = self
101
- for p in w.split(' / ' )[1 :]:
111
+ for p in w.split(" / " )[1 :]:
102
112
if p not in node.children:
103
113
return - 1
104
114
node = node.children[p]
105
- return node.v or - 1
115
+ return node.v
106
116
107
117
108
118
class FileSystem :
@@ -131,11 +141,15 @@ class Trie {
131
141
Map<String , Trie > children = new HashMap<> ();
132
142
int v;
133
143
144
+ Trie (int v ) {
145
+ this . v = v;
146
+ }
147
+
134
148
boolean insert (String w , int v ) {
135
149
Trie node = this ;
136
- String [] ps = w. split(" /" );
150
+ var ps = w. split(" /" );
137
151
for (int i = 1 ; i < ps. length - 1 ; ++ i) {
138
- String p = ps[i];
152
+ var p = ps[i];
139
153
if (! node. children. containsKey(p)) {
140
154
return false ;
141
155
}
@@ -144,30 +158,29 @@ class Trie {
144
158
if (node. children. containsKey(ps[ps. length - 1 ])) {
145
159
return false ;
146
160
}
147
- node. children. put(ps[ps. length - 1 ], new Trie ());
148
- node = node. children. get(ps[ps. length - 1 ]);
149
- node. v = v;
161
+ node. children. put(ps[ps. length - 1 ], new Trie (v));
150
162
return true ;
151
163
}
152
164
153
165
int search (String w ) {
154
166
Trie node = this ;
155
- String [] ps = w. split(" /" );
167
+ var ps = w. split(" /" );
156
168
for (int i = 1 ; i < ps. length; ++ i) {
157
- String p = ps[i];
169
+ var p = ps[i];
158
170
if (! node. children. containsKey(p)) {
159
171
return - 1 ;
160
172
}
161
173
node = node. children. get(p);
162
174
}
163
- return node. v == 0 ? - 1 : node . v ;
175
+ return node. v;
164
176
}
165
177
}
166
178
167
179
class FileSystem {
168
- private Trie trie = new Trie ();
180
+ private Trie trie = new Trie (- 1 );
169
181
170
182
public FileSystem () {
183
+
171
184
}
172
185
173
186
public boolean createPath (String path , int value ) {
@@ -187,58 +200,133 @@ class FileSystem {
187
200
*/
188
201
```
189
202
203
+ ### ** C++**
204
+
205
+ ``` cpp
206
+ class Trie {
207
+ public:
208
+ unordered_map<string, Trie* > children;
209
+ int v;
210
+
211
+ Trie(int v) {
212
+ this->v = v;
213
+ }
214
+
215
+ bool insert (string& w, int v) {
216
+ Trie* node = this;
217
+ auto ps = split(w, '/');
218
+ for (int i = 1; i < ps.size() - 1; ++i) {
219
+ auto p = ps[ i] ;
220
+ if (!node->children.count(p)) {
221
+ return false;
222
+ }
223
+ node = node->children[ p] ;
224
+ }
225
+ if (node->children.count(ps.back())) {
226
+ return false;
227
+ }
228
+ node->children[ ps.back()] = new Trie(v);
229
+ return true;
230
+ }
231
+
232
+ int search(string& w) {
233
+ Trie* node = this;
234
+ auto ps = split(w, '/');
235
+ for (int i = 1; i < ps.size(); ++i) {
236
+ auto p = ps[i];
237
+ if (!node->children.count(p)) {
238
+ return -1;
239
+ }
240
+ node = node->children[p];
241
+ }
242
+ return node->v;
243
+ }
244
+
245
+
246
+ private:
247
+ vector<string > split(string& s, char delim) {
248
+ stringstream ss(s);
249
+ string item;
250
+ vector<string > res;
251
+ while (getline(ss, item, delim)) {
252
+ res.emplace_back(item);
253
+ }
254
+ return res;
255
+ }
256
+ };
257
+
258
+ class FileSystem {
259
+ public:
260
+ FileSystem() {
261
+ trie = new Trie(-1);
262
+ }
263
+
264
+ bool createPath(string path, int value) {
265
+ return trie->insert(path, value);
266
+ }
267
+
268
+ int get(string path) {
269
+ return trie->search(path);
270
+ }
271
+
272
+ private:
273
+ Trie* trie;
274
+ };
275
+
276
+ /**
277
+ * Your FileSystem object will be instantiated and called as such:
278
+ * FileSystem* obj = new FileSystem();
279
+ * bool param_1 = obj->createPath(path,value);
280
+ * int param_2 = obj->get(path);
281
+ * /
282
+ ```
283
+
190
284
### **Go**
191
285
192
286
```go
193
- type Trie struct {
194
- children map [string ]*Trie
287
+ type trie struct {
288
+ children map[string]*trie
195
289
v int
196
290
}
197
291
198
- func newTrie () *Trie {
199
- m := map [string ]*Trie{}
200
- return &Trie{children: m}
292
+ func newTrie(v int) *trie {
293
+ return &trie{map[string]*trie{}, v}
201
294
}
202
295
203
- func (this * Trie ) insert (w string , v int ) bool {
204
- node := this
296
+ func (t *trie ) insert(w string, v int) bool {
297
+ node := t
205
298
ps := strings.Split(w, "/")
206
299
for _, p := range ps[1 : len(ps)-1] {
207
300
if _, ok := node.children[p]; !ok {
208
301
return false
209
302
}
210
- node, _ = node.children [p]
303
+ node = node.children[p]
211
304
}
212
- x := ps[len (ps)-1 ]
213
- if _ , ok := node.children [x]; ok {
305
+ if _, ok := node.children[ps[len(ps)-1]]; ok {
214
306
return false
215
307
}
216
- node.children [x] = newTrie ()
217
- node, _ = node.children [x]
218
- node.v = v
308
+ node.children[ps[len(ps)-1]] = newTrie(v)
219
309
return true
220
310
}
221
311
222
- func (this *Trie ) search (w string ) int {
223
- node := this
224
- for _ , p := range strings.Split (w, " /" )[1 :] {
312
+ func (t *trie) search(w string) int {
313
+ node := t
314
+ ps := strings.Split(w, "/")
315
+ for _, p := range ps[1:] {
225
316
if _, ok := node.children[p]; !ok {
226
317
return -1
227
318
}
228
- node, _ = node.children [p]
229
- }
230
- if node.v == 0 {
231
- return -1
319
+ node = node.children[p]
232
320
}
233
321
return node.v
234
322
}
235
323
236
324
type FileSystem struct {
237
- trie *Trie
325
+ trie *trie
238
326
}
239
327
240
328
func Constructor() FileSystem {
241
- return FileSystem{newTrie ()}
329
+ return FileSystem{trie: newTrie(-1 )}
242
330
}
243
331
244
332
func (this *FileSystem) CreatePath(path string, value int) bool {
@@ -257,6 +345,72 @@ func (this *FileSystem) Get(path string) int {
257
345
*/
258
346
```
259
347
348
+ ### ** TypeScript**
349
+
350
+ ``` ts
351
+ class Trie {
352
+ children: Map <string , Trie >;
353
+ v: number ;
354
+
355
+ constructor (v : number ) {
356
+ this .children = new Map <string , Trie >();
357
+ this .v = v ;
358
+ }
359
+
360
+ insert(w : string , v : number ): boolean {
361
+ let node: Trie = this ;
362
+ const ps = w .split (' /' ).slice (1 );
363
+ for (let i = 0 ; i < ps .length - 1 ; ++ i ) {
364
+ const p = ps [i ];
365
+ if (! node .children .has (p )) {
366
+ return false ;
367
+ }
368
+ node = node .children .get (p )! ;
369
+ }
370
+ if (node .children .has (ps [ps .length - 1 ])) {
371
+ return false ;
372
+ }
373
+ node .children .set (ps [ps .length - 1 ], new Trie (v ));
374
+ return true ;
375
+ }
376
+
377
+ search(w : string ): number {
378
+ let node: Trie = this ;
379
+ const ps = w .split (' /' ).slice (1 );
380
+ for (const p of ps ) {
381
+ if (! node .children .has (p )) {
382
+ return - 1 ;
383
+ }
384
+ node = node .children .get (p )! ;
385
+ }
386
+ return node .v ;
387
+ }
388
+ }
389
+
390
+ class FileSystem {
391
+ trie: Trie ;
392
+
393
+ constructor () {
394
+ this .trie = new Trie (- 1 );
395
+ }
396
+
397
+ createPath(path : string , value : number ): boolean {
398
+ return this .trie .insert (path , value );
399
+ }
400
+
401
+ get(path : string ): number {
402
+ return this .trie .search (path );
403
+ }
404
+ }
405
+
406
+ /**
407
+ * Your FileSystem object will be instantiated and called as such:
408
+ * var obj = new FileSystem()
409
+ * var param_1 = obj.createPath(path,value)
410
+ * var param_2 = obj.get(path)
411
+ */
412
+ ```
413
+
260
414
### ** ...**
261
415
262
416
```
0 commit comments