LeetCode 208. Implement Trie (Prefix Tree) (实现Trie树)

原题

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.

Reference Answer

补充知识

实现字典树。字典树:
《LeetCode 208. Implement Trie (Prefix Tree) (实现Trie树)》

上图是一棵Trie树,表示了关键字集合{“a”, “to”, “tea”, “ted”, “ten”, “i”, “in”, “inn”} 。从上图可以归纳出Trie树的基本性质:

根节点不包含字符,除根节点外的每一个子节点都包含一个字符。
从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。
每个节点的所有子节点包含的字符互不相同。
通常在实现的时候,会在节点结构中设置一个标志,用来标记该结点处是否构成一个单词(关键字)。

可以看出,Trie树的关键字一般都是字符串,而且Trie树把每个关键字保存在一条路径上,而不是一个结点中。另外,两个有公共前缀的关键字,在Trie树中前缀部分的路径相同,所以Trie树又叫做前缀树(Prefix Tree)。

思路分析
每个节点的子孩子都是一个字典,根据字典查找下一个位置的节点,就像字典一样。同事用isword保存当前是不是一个词(也可能是路径中的点)。

这道题自己开始想简单了,想着只用list进行操作就好了,没想到使用Prefix Tree结构,结果发现,时间复杂度超出要求,必须还是要回到Prefix Tree结构

My Code
时间复杂度超过要求,失败!

class Trie:

    def __init__(self):
        """ Initialize your data structure here. """
        self.res = []
  

    def insert(self, word):
        """ Inserts a word into the trie. :type word: str :rtype: void """
        self.res.insert(0, word)
    

    def search(self, word):
        """ Returns if the word is in the trie. :type word: str :rtype: bool """
        for x in self.res:
            if x == word:
                return True
        return False

    def startsWith(self, prefix):
        """ Returns if there is any word in the trie that starts with the given prefix. :type prefix: str :rtype: bool """
        # if not prefix:
        # return True
        if not self.res:
            return False
        
        for count in self.res:
            base = count
            if base[0] != prefix[0]:
                continue
            len_base = len(base)
            len_target = len(prefix)
            if len_target > len_base:
                continue
            if prefix == base[:len_target]:
                return True
        return False
    


# 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)
        

Reference Code (Prefix Tree)

class Node(object):
    def __init__(self):
        self.children = collections.defaultdict(Node)
        self.isword = False

class Trie(object):

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

    def insert(self, word):
        """ Inserts a word into the trie. :type word: str :rtype: void """
        current = self.root
        for w in word:
            current = current.children[w]
        current.isword = True

    def search(self, word):
        """ Returns if the word is in the trie. :type word: str :rtype: bool """
        current = self.root
        for w in word:
            current = current.children.get(w)
            if current == None:
                return False
        return current.isword

    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 w in prefix:
            current = current.children.get(w)
            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)

Note:

  1. 注意Python结构体的实现及使用方式;
  2. collections.defaultdict(Node)的使用方式,其中collections.defaultdict()中可以为int,为strlist,也可以自定义结构类型,如本题中的Node

参考文献

[1] https://blog.csdn.net/fuxuemingzhu/article/details/79388432

    原文作者:Trie树
    原文地址: https://blog.csdn.net/Dby_freedom/article/details/84747783
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞