[Leetcode] Implement Trie (Prefix Tree) 前綴表達樹

前綴表達樹又稱字典樹,是一種多叉樹結構,主要用於快速搜索。本題要求設計前綴表達樹,實現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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章