1
+ """
2
+ 前缀树又叫字典树,该树会覆盖多个相同的字符以形成空间上的优势。
3
+
4
+ 如:
5
+ rat 与 rain
6
+ r
7
+ a
8
+ t i
9
+ n
10
+ 最终会形成这样的树。
11
+
12
+ 字典树有多种实现方式,下面直接用了列表(数组)来实现。
13
+ 测试用例:
14
+ https://leetcode.com/problems/implement-trie-prefix-tree/description/
15
+
16
+ 使用Python 中的字典可以直接形成这种树,所以弃用这种方式,用类的思路实现了一下。
17
+
18
+ """
19
+
20
+ class TrieNode (object ):
21
+ # __slots__ 考虑到TrieNode会大量创建,使用 __slot__来减少内存的占用。
22
+ # 在测试的15个例子中:
23
+ # 使用 __slots__会加快创建,平均的耗时为290ms-320ms。
24
+ # 而不使用则在 340ms-360ms之间。
25
+ # 创建的越多效果越明显。
26
+ # 当然,使用字典而不是类的方式会更加更加更加高效。
27
+ __slots__ = {'value' , 'nextNodes' , 'breakable' }
28
+
29
+ def __init__ (self , value , nextNode = None ):
30
+ self .value = value
31
+ if nextNode :
32
+ self .nextNodes = [nextNode ]
33
+ else :
34
+ self .nextNodes = []
35
+ self .breakable = False
36
+
37
+ def addNext (self , nextNode ):
38
+ self .nextNodes .append (nextNode )
39
+
40
+ def setBreakable (self , enable ):
41
+ self .breakable = enable
42
+
43
+ def __eq__ (self , other ):
44
+ return self .value == other
45
+
46
+
47
+
48
+ class Trie (object ):
49
+
50
+ def __init__ (self ):
51
+ """
52
+ Initialize your data structure here.
53
+ """
54
+ self .root = []
55
+
56
+
57
+ def insert (self , word ):
58
+ """
59
+ Inserts a word into the trie.
60
+ :type word: str
61
+ :rtype: void
62
+ """
63
+ self .makeATrieNodes (word )
64
+
65
+ def search (self , word ):
66
+ """
67
+ Returns if the word is in the trie.
68
+ :type word: str
69
+ :rtype: bool
70
+ """
71
+ for i in self .root :
72
+ if i == word [0 ]:
73
+
74
+ return self ._search (i , word [1 :])
75
+ return False
76
+
77
+ def _search (self , root , word ):
78
+ if not word :
79
+ if root .breakable :
80
+ return True
81
+ return False
82
+ if not root .nextNodes :
83
+ return False
84
+
85
+ for i in root .nextNodes :
86
+ if i == word [0 ]:
87
+ return self ._search (i , word [1 :])
88
+
89
+ return False
90
+
91
+ def startsWith (self , prefix ):
92
+ """
93
+ Returns if there is any word in the trie that starts with the given prefix.
94
+ :type prefix: str
95
+ :rtype: bool
96
+ """
97
+ for i in self .root :
98
+ if i == prefix [0 ]:
99
+ return self ._startWith (i , prefix [1 :])
100
+ return False
101
+
102
+ def _startWith (self , root , prefix ):
103
+ if not prefix :
104
+ return True
105
+
106
+ if not root .nextNodes :
107
+ return False
108
+
109
+ for i in root .nextNodes :
110
+ if i == prefix [0 ]:
111
+ return self ._startWith (i , prefix [1 :])
112
+
113
+ return False
114
+
115
+ def makeATrieNodes (self , word ):
116
+ for j in self .root :
117
+ if word [0 ] == j :
118
+ rootWord = j
119
+ break
120
+ else :
121
+
122
+ rootWord = TrieNode (word [0 ])
123
+ self .root .append (rootWord )
124
+ for i in word [1 :]:
125
+ nextNode = TrieNode (i )
126
+ rootWord .addNext (nextNode )
127
+ rootWord = nextNode
128
+ rootWord .setBreakable (True )
129
+ return
130
+
131
+ # has the letter.
132
+ word = word [1 :]
133
+ while 1 :
134
+ if not word :
135
+ rootWord .setBreakable (True )
136
+ break
137
+
138
+ for i in rootWord .nextNodes :
139
+ if i == word [0 ]:
140
+ rootWord = i
141
+ word = word [1 :]
142
+ break
143
+ else :
144
+ for i in word :
145
+ nextNode = TrieNode (i )
146
+ rootWord .addNext (nextNode )
147
+ rootWord = nextNode
148
+ rootWord .setBreakable (True )
149
+ break
0 commit comments