LeetCode 208. Implement Trie (Prefix Tree) 实现 Trie (前缀树)(C++/Java)

题目:

Implement a trie with insertsearch, 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.

分析:

实现一个前缀树,包含insertsearch, and startsWith三个方法,分别对应插入,搜索单词和搜索前缀三个方法。

前缀树在这里就不多说了,网上的介绍有很多。

下面说一下具体的实现。

因为只有a-z共26个英文字母,所有开辟一个26大小的数组用来保存节点,isEnd用来表示该节点是否为单词终止节点,例如apple,那么在e节点时应该将isEnd置为true,以便搜索方法查询单词。

Trie* node[26] = {nullptr};
bool isEnd = false;

insert插入一个单词,遍历单词的每一个字符,从根节点开始查询对应位置的数组是否为空,如果为空就在对应位置新建节点,然后继续,在最后一个字符对应的位置isEnd记为true

void insert(string word) {
    Trie* p = this;
    for(const char ch:word){
        if(p->node[ch-'a'] == nullptr)
            p->node[ch-'a'] = new Trie();
        p = p->node[ch-'a'];
    }
    p->isEnd = true;
}

search, and startsWith可以通过一个辅助函数来实现,遍历单词的字符,如果对应位置为null则表示前缀树中没有这个字符,返回null即可,否自返回查询到的最后一个结点。通过结点来判断单词是否存在,如果isEnd为true则search返回true。

Trie* mySearch(string word){
        Trie *p = this;
        for (auto c : word){
            if (p->node[c - 'a'] == nullptr) return nullptr;
            p = p->node[c - 'a'];
        }
        return p;
    }

程序:

C++

class Trie {
public:
    /** Initialize your data structure here. */
    Trie() {
        //root = new Trie();
    }

    /** Inserts a word into the trie. */
    void insert(string word) {
        Trie* p = this;
        for(const char ch:word){
            if(p->node[ch-'a'] == nullptr)
                p->node[ch-'a'] = new Trie();
            p = p->node[ch-'a'];
        }
        p->isEnd = true;
    }
    
    /** Returns if the word is in the trie. */
    bool search(string word) {
        Trie* res = mySearch(word);
        return res && res->isEnd;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        return mySearch(prefix) != nullptr; 
    }
private:
    //Trie* root;
    Trie* node[26] = {nullptr};
    bool isEnd = false;

    Trie* mySearch(string word){
        Trie *p = this;
        for (auto c : word){
            if (p->node[c - 'a'] == nullptr) return nullptr;
            p = p->node[c - 'a'];
        }
        return p;
    }
};

Java

class Trie {

    /** Initialize your data structure here. */
    public Trie() {
        
    }
    
    /** Inserts a word into the trie. */
    public void insert(String word) {
        Trie p = this;
        char[] w = word.toCharArray();
        for(char ch:w){
            if(p.node[ch - 'a'] == null)
                p.node[ch - 'a'] = new Trie();
            p = p.node[ch - 'a'];
        }
        p.isEnd = true;
    }
    
    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        Trie res = find(word);
        return res != null && res.isEnd;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        return find(prefix) != null;
    }
    
    private Trie[] node = new Trie[26];
    private boolean isEnd = false;
    private Trie find(String word){
        Trie p = this;
        char[] w = word.toCharArray();
        for(char ch:w){
            if(p.node[ch - 'a'] == null)
                return null;
            p = p.node[ch - 'a'];
        }
        return p;
    }
}

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.insert(word);
 * boolean param_2 = obj.search(word);
 * boolean param_3 = obj.startsWith(prefix);
 */
原文地址:https://www.cnblogs.com/silentteller/p/12342869.html