原题
Implement a trie with insert
, search
, and startsWith
methods.
Example:
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple"); // returns true
trie.search("app"); // returns false
trie.startsWith("app"); // returns true
trie.insert("app");
trie.search("app"); // returns true
Note:
- You may assume that all inputs are consist of lowercase letters
a-z
. - All inputs are guaranteed to be non-empty strings.
Reference Answer
补充知识
实现字典树。字典树:
上图是一棵Trie树,表示了关键字集合{“a”, “to”, “tea”, “ted”, “ten”, “i”, “in”, “inn”} 。从上图可以归纳出Trie树的基本性质:
根节点不包含字符,除根节点外的每一个子节点都包含一个字符。
从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。
每个节点的所有子节点包含的字符互不相同。
通常在实现的时候,会在节点结构中设置一个标志,用来标记该结点处是否构成一个单词(关键字)。
可以看出,Trie树的关键字一般都是字符串,而且Trie树把每个关键字保存在一条路径上,而不是一个结点中。另外,两个有公共前缀的关键字,在Trie树中前缀部分的路径相同,所以Trie树又叫做前缀树(Prefix Tree)。
思路分析
每个节点的子孩子都是一个字典,根据字典查找下一个位置的节点,就像字典一样。同事用isword保存当前是不是一个词(也可能是路径中的点)。
这道题自己开始想简单了,想着只用list进行操作就好了,没想到使用Prefix Tree结构,结果发现,时间复杂度超出要求,必须还是要回到Prefix Tree结构
My Code
时间复杂度超过要求,失败!
class Trie:
def __init__(self):
"""
Initialize your data structure here.
"""
self.res = []
def insert(self, word):
"""
Inserts a word into the trie.
:type word: str
:rtype: void
"""
self.res.insert(0, word)
def search(self, word):
"""
Returns if the word is in the trie.
:type word: str
:rtype: bool
"""
for x in self.res:
if x == word:
return True
return False
def startsWith(self, prefix):
"""
Returns if there is any word in the trie that starts with the given prefix.
:type prefix: str
:rtype: bool
"""
# if not prefix:
# return True
if not self.res:
return False
for count in self.res:
base = count
if base[0] != prefix[0]:
continue
len_base = len(base)
len_target = len(prefix)
if len_target > len_base:
continue
if prefix == base[:len_target]:
return True
return False
# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)
Reference Code (Prefix Tree)
class Node(object):
def __init__(self):
self.children = collections.defaultdict(Node)
self.isword = False
class Trie(object):
def __init__(self):
"""
Initialize your data structure here.
"""
self.root = Node()
def insert(self, word):
"""
Inserts a word into the trie.
:type word: str
:rtype: void
"""
current = self.root
for w in word:
current = current.children[w]
current.isword = True
def search(self, word):
"""
Returns if the word is in the trie.
:type word: str
:rtype: bool
"""
current = self.root
for w in word:
current = current.children.get(w)
if current == None:
return False
return current.isword
def startsWith(self, prefix):
"""
Returns if there is any word in the trie that starts with the given prefix.
:type prefix: str
:rtype: bool
"""
current = self.root
for w in prefix:
current = current.children.get(w)
if current == None:
return False
return True
# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)
Note:
- 注意Python结构体的实现及使用方式;
collections.defaultdict(Node)
的使用方式,其中collections.defaultdict()
中可以为int
,为str
及list
,也可以自定义结构类型,如本题中的Node
;
参考文献
[1] https://blog.csdn.net/fuxuemingzhu/article/details/79388432