原题如下:
实现一个 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
一个很容易想到的方法就是把每个str 插入到map里,但是startsWith()函数却不好查!!当然你也可以尝试一下再开一个map把每个str的【0-i】(i>=0&&i<=str.size()-1)存进去(LZ是没有试过。。。。)
其实 这道题就是图的深度优先遍历和广度优先遍历的集合,只不过,我们不要直接把str存进去,把str的每个元素接在他前面那个元素的后面(如果当前元素已经存在,可以省略当前这一步)
举个例子 对于 abc app adx bc 这3个str而言他们构成的 map 集是这样的
a
/|\
b p d
| | |
c p x
b
|
c
注意这个bc
即每个单词的开头为一个图的入口,进入这个图后,对于一个str 我们广度优先遍历找到str【i】,再向下深度遍历str【i+1】,,insert构造这个图的时候也是同样道理
代码如下ps(lz为了偷懒,又开了一个unordered_map<>search_str,便于查str,按照start_with()思绪继续查下去,就是search()):
struct Trie_node
{
char val;
vector<Trie_node*>next;
Trie_node(char x) :val(x){}
};
class Trie {
public:
/** Initialize your data structure here. */
Trie() {
}
/** Inserts a word into the trie. */
Trie_node* find_or_insert(vector<Trie_node*> &next, char &a){
if (next.size() == 0){
Trie_node *tmp = new Trie_node(a);
next.push_back(tmp);
return tmp;
}
else{
for (int i = 0; i <= next.size() - 1; i++){
if (next[i]->val == a) return next[i];
}
Trie_node *tmp = new Trie_node(a);
next.push_back(tmp);
return tmp;
}
}
void insert(string word) {
search_str[word]++;
unordered_map<char, Trie_node *>::iterator iter = my_map.find(word[0]);
if (iter == my_map.end()){
Trie_node *head = new Trie_node(word[0]);
Trie_node *p = head;
for (int i = 1; i <= word.size() - 1; i++)
p = find_or_insert(p->next, word[i]);
my_map[word[0]] = head;
}
else{
Trie_node *p = (*iter).second;
for (int i = 1; i <= word.size() - 1; i++)
p = find_or_insert(p->next, word[i]);
}
}
/** Returns if the word is in the trie. */
bool search(string word) {
unordered_map<string, int>::iterator iter = search_str.find(word);
if (iter == search_str.end())return false;
else return true;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
Trie_node* only_find(vector<Trie_node*> &next, char &a){
if (next.size() == 0)
return nullptr;
else{
for (int i = 0; i <= next.size() - 1; i++){
if (next[i]->val == a) return next[i];
}
return nullptr;
}
}
bool startsWith(string prefix) {
unordered_map<char, Trie_node *>::iterator iter = my_map.find(prefix[0]);
if (iter == my_map.end())return false;
Trie_node *p = (*iter).second;
for (int i = 1; i <= prefix.size() - 1; i++){
p = only_find(p->next, prefix[i]);
if (p == nullptr)return false;
}
return true;
}
private:
unordered_map<char, Trie_node *>my_map;
unordered_map<string, int>search_str;
};