题目:
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 lettersa-z
.
All inputs are guaranteed to be non-empty strings.
解释:
实现字典树
python中用字典来表示子结点,用一个bool变量表示是否有一个单词到这个结点处结束,但是感觉这种写法并不是经典写法,而且也比较难以理解,更经典的写法应该是默认每个结点都有26个子节点(如果是英文单词的话),也可以把bool类型的is_word变成int类型的count,实现词频统计:
from collections import defaultdict
class TrieNode(object):
def __init__(self):
self.children=defaultdict(TrieNode)
self.is_word=False
class Trie(object):
def __init__(self):
"""
Initialize your data structure here.
"""
self.root=TrieNode()
def insert(self, word):
"""
Inserts a word into the trie.
:type word: str
:rtype: void
"""
current=self.root
for letter in word:
current=current.children[letter]
#在最后一个字母的位置,is_word变为True
current.is_word=True
def search(self, word):
"""
Returns if the word is in the trie.
:type word: str
:rtype: bool
"""
current=self.root
for letter in word:
current=current.children.get(letter)
#如果不存在这个键
if current==None:
return False
#如果不是一个完整的单词,那么也是返回False,比如,树中存在"abc"但是word="ab"的情况
return current.is_word
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 letter in prefix:
current=current.children.get(letter)
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)
啊,终于自己摸索着写出c++代码了:
#include<map>
using namespace std;
struct TrieNode {
bool isWord;
char c;
map<char,TrieNode*> children;
TrieNode(char x) : c(x),isWord(false){}
TrieNode() : isWord(false){}
};
class Trie {
public:
/** Initialize your data structure here. */
TrieNode* root;
Trie() {
root=new TrieNode();
}
/** Inserts a word into the trie. */
void insert(string word) {
TrieNode* current=root;
for(auto letter:word)
{
if (!current->children.count(letter))
current->children[letter]=new TrieNode(letter);
current=current->children[letter];
}
current->isWord=true;
}
/** Returns if the word is in the trie. */
bool search(string word) {
TrieNode * current=root;
for(int i=0;i<word.size();i++ )
{
char letter=word[i];
if (!current->children.count(letter))
return false;
current=current->children[letter];
}
return current->isWord;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
TrieNode * current=root;
for(auto letter:prefix)
{
if (!current->children.count(letter))
return false;
current=current->children[letter];
}
return true;
}
};
/**
* Your Trie object will be instantiated and called as such:
* Trie obj = new Trie();
* obj.insert(word);
* bool param_2 = obj.search(word);
* bool param_3 = obj.startsWith(prefix);
*/
注意新建结点之前一定要判断这个子节点是否存在,如果存在就不新建了,盲目新建会导致把以前的路径删除,使得答案不对。
总结:
字典树相关的知识: