前綴表達樹又稱字典樹,是一種多叉樹結構,主要用於快速搜索。本題要求設計前綴表達樹,實現insert, search, 和 startsWith三個方法。
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.
解題思路:
首先我們要設計一下TireNode節點,這裏用is_word標記當前節點是否爲某一個單詞的結尾。
節點對於子節點的表達,既可以採用動態數組,也可以採用哈希表來存儲子節點。
其中,採用動態數組時,需要注意一定要在節點的析構函數中刪除子節點的指針,以免內存泄漏。
class Trie {
private:
struct TrieNode
{
TrieNode():is_word(false),children(26,nullptr){}
//must delete TrieNode* in destructor
~TrieNode(){
for(auto child : children)
if(child)
delete child;
}
bool is_word;
vector<TrieNode*> children;
};
std::unique_ptr<TrieNode> _root;
class Trie {
private:
struct TrieNode {
TrieNode():is_word(false){}
~TrieNode() {
for (auto& kv : children)
if (kv.second) delete kv.second;
}
bool is_word;
//use hash map
unordered_map<char, TrieNode*> children;
std::unique_ptr<TrieNode> root_;
};
insert方法的實現很簡單:
/** Inserts a word into the trie. */
void insert(const string& word) {
TrieNode* p = root_.get();
for (const char c : word) {
if (!p->children.count(c))
p->children[c] = new TrieNode();
p = p->children[c];
}
p->is_word = true;
}
最後,實現search和startsWith,我們添加一個輔助函數find尋找子節點。
const TrieNode* find(const string& prefix) const {
const TrieNode* p = root_.get();
for (const char c : prefix) {
if (!p->children.count(c)) return nullptr;
p = p->children.at(c);
}
return p;
}
/** Returns if the word is in the trie. */
bool search(const string& word) const {
const TrieNode* p = find(word);
return p && p->is_word;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(const string& prefix) const {
return find(prefix) != nullptr;
}
代碼清單: https://github.com/ShulinLiu/DataStructure-Algorithm/blob/master/LeetCode/208_PrefixTree.hpp