难度:中等
问题描述:
实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。
示例:
Trie trie = new Trie();
trie.insert(“apple”);
trie.search(“apple”); // 返回 true
trie.search(“app”); // 返回 false
trie.startsWith(“app”); // 返回 true
trie.insert(“app”);
trie.search(“app”); // 返回 true
说明:
你可以假设所有的输入都是由小写字母 a-z 构成的。
保证所有输入均为非空字符串。
思路:先建树,然后再查找,利用了哈希表,用来存储该节点下的所有孩子及其孩子节点存储的字符,且在每个单词的末端做一个标记号,来代表该节点为单词的叶子节点。
#include <hasp_map>
class TrieNode{
public:
char c; //当前节点对应的字符
bool leaf=false;
map<char,TrieNode>* children=new map<char,TrieNode>();
TrieNode(){} //构造函数
TrieNode(char x):c(x){}
};
class Trie {
private:
TrieNode *root; //私有变量
public:
/** Initialize your data structure here. */
Trie() { //构造函数
root=new TrieNode();
}
/** Inserts a word into the trie. */
void insert(string word) {
map<char,TrieNode> *children=root->children;
for(int i=0;i<word.size();i++){
char c=word[i];
TrieNode *t;
if(children->count(c)){ //判断是否包含这个字符
map<char,TrieNode>::iterator iter=children->find(c);
t=&iter->second;
if(i==word.size()-1) t->leaf=true; //搜索到词的结尾,标志为true
}
else{
t=new TrieNode(c);
if(i==word.size()-1) t->leaf=true;
children->insert(pair<char,TrieNode>(c,*t));
}
children=t->children;
}
}
/** Returns if the word is in the trie. */
bool search(string word) {
if(root->children->size()==0) return false; //当树为空的时候,直接返回false
TrieNode* sWord=searchNode(word);
return sWord!=NULL && sWord->leaf;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
return searchNode(prefix)!=NULL;
}
TrieNode* searchNode(string word){
map<char,TrieNode> *children=root->children;
TrieNode *t=NULL;
for(int i=0;i<word.size();i++){
char c=word[i];
if(!children->count(c)) return NULL;
map<char,TrieNode>::iterator iter=children->find(c);
t=&iter->second;
children=t->children;
}
return t;
}
};
/**
* 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);
*/