208. Implement Trie (Prefix Tree)(python+cpp)

题目:

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.

解释:
实现字典树
python中用字典来表示子结点,用一个bool变量表示是否有一个单词到这个结点处结束,但是感觉这种写法并不是经典写法,而且也比较难以理解,更经典的写法应该是默认每个结点都有26个子节点(如果是英文单词的话),也可以把bool类型的is_word变成int类型的count,实现词频统计:

from collections import defaultdict
class TrieNode(object):
    def __init__(self):
        self.children=defaultdict(TrieNode)
        self.is_word=False
class Trie(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.root=TrieNode()

    def insert(self, word):
        """
        Inserts a word into the trie.
        :type word: str
        :rtype: void
        """
        current=self.root
        for letter in word:
            current=current.children[letter]
        #在最后一个字母的位置,is_word变为True
        current.is_word=True          

    def search(self, word):
        """
        Returns if the word is in the trie.
        :type word: str
        :rtype: bool
        """
        current=self.root
        for letter in word:
            current=current.children.get(letter)
            #如果不存在这个键
            if current==None:
                return False
        #如果不是一个完整的单词,那么也是返回False,比如,树中存在"abc"但是word="ab"的情况
        return current.is_word

    def startsWith(self, prefix):
        """
        Returns if there is any word in the trie that starts with the given prefix.
        :type prefix: str
        :rtype: bool
        """
        current=self.root
        for letter in prefix:
            current=current.children.get(letter)
            if current==None:
                return False
        return True

# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)

啊,终于自己摸索着写出c++代码了:

#include
using namespace std;
struct TrieNode {
    bool isWord;
    char c;
    map<char,TrieNode*> children;
    TrieNode(char x) : c(x),isWord(false){}
    TrieNode() : isWord(false){}
};
class Trie {
public:
    /** Initialize your data structure here. */
    TrieNode* root;
    Trie() {
        
        root=new TrieNode();
    }
    
    /** Inserts a word into the trie. */
    void insert(string word) {
        TrieNode* current=root;
        for(auto letter:word)
        {
            if (!current->children.count(letter))
                current->children[letter]=new TrieNode(letter);
            current=current->children[letter];
        }
        current->isWord=true;
    }
    
    /** Returns if the word is in the trie. */
    bool search(string word) {
        TrieNode * current=root;
        for(int i=0;i<word.size();i++ )
        {
            char letter=word[i];
            if (!current->children.count(letter))
                return false;           
            current=current->children[letter];
        }
        return current->isWord;  
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        TrieNode * current=root;
        for(auto letter:prefix)
        {
            if (!current->children.count(letter))
                return false;
            current=current->children[letter];
        }
        return true;
    }
};

/**
 * 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);
 */

注意新建结点之前一定要判断这个子节点是否存在,如果存在就不新建了,盲目新建会导致把以前的路径删除,使得答案不对。
总结:
字典树相关的知识:

Trie树(Prefix Tree)介绍
6天通吃树结构—— 第五天 Trie树

你可能感兴趣的:(LeetCode)