zoukankan      html  css  js  c++  java
  • [LeetCode] 208. Implement Trie (Prefix Tree) 实现字典树(前缀树)

    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.

    实现一个数据结构:字典树(前缀树或单词查找树),具备insert, search, startsWith的功能。参考董的博客:数据结构之Trie树

    Trie树,又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构,如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树。Trie树可以利用字符串的公共前缀来节约存储空间。

    Trie树的基本性质可以归纳为:

    (1)根节点不包含字符,除根节点以外每个节点只包含一个字符。

    (2)从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。

    (3)每个节点的所有子节点包含的字符串不相同。

    下图是一个保存了8个键的trie结构,"A", "to", "tea", "ted", "ten", "i", "in", and "inn"

    Trie树复杂度:

    (1)插入、查找的时间复杂度均为O(n),其中n为字符串长度。

    (2) 空间复杂度是26^n级别的,非常庞大(可采用双数组实现改善)。

    实施方法:因为只用26个字母,所以可以用数组记录,数组元素为TrieNode。

    Java:

    class TrieNode {
        private TrieNode[] children;
        public boolean hasWord;
        
        // Initialize your data structure here.
        public TrieNode() {
            children = new TrieNode[26];
            hasWord = false;
        }
        
        public void insert(String word, int index) {
            if (index == word.length()) {
                this.hasWord = true;
                return;
            }
            
            int pos = word.charAt(index) - 'a';
            if (children[pos] == null) {
                children[pos] = new TrieNode();
            }
            children[pos].insert(word, index + 1);
        }
        
        public TrieNode find(String word, int index) {
            if (index == word.length()) {
                return this;
            }
            
            int pos = word.charAt(index) - 'a';
            if (children[pos] == null) {
                return null;
            }
            return children[pos].find(word, index + 1);
        }
    }
    
    public class Trie {
        private TrieNode root;
    
        public Trie() {
            root = new TrieNode();
        }
    
        // Inserts a word into the trie.
        public void insert(String word) {
            root.insert(word, 0);
        }
    
        // Returns if the word is in the trie.
        public boolean search(String word) {
            TrieNode node = root.find(word, 0);
            return (node != null && node.hasWord);
        }
    
        // Returns if there is any word in the trie
        // that starts with the given prefix.
        public boolean startsWith(String prefix) {
            TrieNode node = root.find(prefix, 0);
            return node != null;
        }
    } 

    Python:  Time: O(n), per operation,  Space: O(1)

    class TrieNode:
      def __init__(self):
        # Initialize your data structure here.
        self.childs = dict()
        self.isWord = False
    
    class Trie:
      def __init__(self):
        self.root = TrieNode()
    
      # @param {string} word
      # @return {void}
      # Inserts a word into the trie.
      def insert(self, word):
        node = self.root
        for letter in word:
          child = node.childs.get(letter)
          if child is None:
            child = TrieNode()
            node.childs[letter] = child
          node = child
        node.isWord = True
    
      # @param {string} word
      # @return {boolean}
      # Returns if the word is in the trie.
      def search(self, word):
        node = self.root
        for letter in word:
          node = node.childs.get(letter)
          if node is None:
            return False
        return node.isWord
    
      # @param {string} prefix
      # @return {boolean}
      # Returns if there is any word in the trie
      # that starts with the given prefix.
      def startsWith(self, prefix):
        node = self.root
        for letter in prefix:
          node = node.childs.get(letter)
          if node is None:
            return False
        return True 

    Python:

    class TrieNode:
        def __init__(self):
            self.is_string = False
            self.leaves = {}
            
    
    class Trie:
    
        def __init__(self):
            self.root = TrieNode()
    
        def insert(self, word):
            cur = self.root
            for c in word:
                if not c in cur.leaves:
                    cur.leaves[c] = TrieNode()
                cur = cur.leaves[c]
            cur.is_string = True
    
        def search(self, word):
            node = self.childSearch(word)
            if node:
                return node.is_string
            return False        
    
        def startsWith(self, prefix):
            return self.childSearch(prefix) is not None
    
        def childSearch(self, word):
            cur = self.root
            for c in word:
                if c in cur.leaves:
                    cur = cur.leaves[c]
                else:
                    return None
            return cur
    

    C++:

    class TrieNode {
    public:
        // Initialize your data structure here.
        TrieNode() : is_string(false) {
            
        }
        bool is_string;
        unordered_map<char, TrieNode *> leaves;
    };
    
    class Trie {
    public:
        Trie() {
            root_ = new TrieNode();
        }
    
        void insert(string word) {
            auto *cur = root_;
            for (const auto& c : word) {
                if (!cur->leaves.count(c)) {
                    cur->leaves[c] = new TrieNode();
                }
                cur = cur->leaves[c];
            }
            cur->is_string = true;
        }
    
        bool search(string word) {
            auto *node = childSearch(word);
            if (node) {
                return node->is_string;
            }
            return false;   
        }
    
        bool startsWith(string prefix) {
            return childSearch(prefix);
        }
    
        TrieNode *childSearch(const string& word) {
            auto *cur = root_;
            for (const auto& c : word) {
                if (cur->leaves.count(c)) {
                    cur = cur->leaves[c];
                } else {
                    return nullptr;
                }
            }
            return cur;
        }
    
    private:
        TrieNode *root_;
    };
    

     

    All LeetCode Questions List 题目汇总

      

  • 相关阅读:
    OpenCV---直方图反向投影
    OpenCV---直方图的应用(均衡化和图像比较)
    ASP.NET WEB SERVICE 创建、部署与使用
    DataSet和DataTable有用的方法
    黑客网站
    局域网中工作组和域之间的差别
    索引使用原则(精)
    C# Web Service 初级教学
    Extjs下拉多选框
    如何在UltraEdit中高亮显示PB代码
  • 原文地址:https://www.cnblogs.com/lightwindy/p/8520820.html
Copyright © 2011-2022 走看看