繁体   English   中英

Leetcode Python 208. 实现 Trie(前缀树)

[英]Leetcode Python 208. Implement Trie (Prefix Tree)

有人可以说我的代码有什么问题吗,当我下载特定测试用例时,它通过了除最后一个测试用例之外的所有测试用例,预期输出和实际输出似乎相同,问题是https://leetcode.com/problems/实现-trie-prefix-tree/description/

编辑1:这是代码:

class Trie:

def __init__(self):
    """
    Initialize your data structure here.
    """
    self.data = None
    self.children = {}
    self.isWord = False

def insert(self, word):
    """
    Inserts a word into the trie.
    :type word: str
    :rtype: void
    """
    if len(word) == 0:
        return
    if word[0] not in self.children:
        self.children[word[0]] = Trie()
        self.insertHelper(word[1:], self.children[word[0]])
    else:
        self.insertHelper(word[1:], self.children[word[0]])

    if len(word) == 1:
        self.isWord = True

def insertHelper(self, word, trie):
    if len(word) == 0:
        return

    if word[0] not in trie.children:
        trie.children[word[0]] = Trie()
        trie.insertHelper(word[1:], trie.children[word[0]])
    else:
        trie.insertHelper(word[1:], trie.children[word[0]])

    if len(word) == 1:
        trie.isWord = True





def search(self, word):
    """
    Returns if the word is in the trie.
    :type word: str
    :rtype: bool
    """
    if len(word) == 1 and word[0] in self.children and self.isWord:
        return True
    elif len(word) == 0:
        return False

    if word[0] in self.children:
        return self.searchHelper(word[1:], self.children[word[0]])
    else:
        return False

def searchHelper(self, word, trie):
    if len(word) == 1 and word[0] in trie.children and trie.isWord:
        return True
    elif len(word) == 0:
        return False

    if word[0] in trie.children:
        return self.searchHelper(word[1:], trie.children[word[0]])
    else:
        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 len(prefix) == 0:
        return False
    if prefix[0] in self.children:
        return self.startsWithHelper(prefix[1:], self.children[prefix[0]])
    else:
        return False

def startsWithHelper(self, prefix, trie):
    if len(prefix) == 0:
        return True

    if prefix[0] in trie.children:
        return trie.startsWithHelper(prefix[1:], trie.children[prefix[0]])
    else:
        return False

提前致谢。

我注意到的一个怪癖是将一个空前缀传递给startsWith() 如果此方法以 Python str方法startswith()为模型,那么我们期望True

>>> "apple".startswith("")
True
>>>

但是在这种情况下,您的 Trie 会返回False

>>> t = Trie()
>>> t.insert("apple")
>>> t.startsWith("")
False
>>>

下面是我对您的代码的修改,主要是为了理解它,但我也发现您有冗余,尤其是您的Helper函数。 这段代码修复了上面提到的怪癖,并且是 Python 3 特定的:

class Trie:

    def __init__(self):
        self.children = {}
        self.isWord = False

    def insert(self, word):
        """
        Inserts a word into the trie.
        :type word: str (or list internally upon recursion)
        :rtype: None
        """

        if not word:
            return

        head, *tail = word

        if head not in self.children:
            self.children[head] = Trie()

        trie = self.children[head]

        if tail:
            trie.insert(tail)
        else:
            self.isWord = True

    def search(self, word):
        """
        Returns True if the word is in the trie.
        :type word: str (or list internally upon recursion)
        :rtype: bool
        """

        if not word:
            return False

        head, *tail = word

        if head in self.children:
            if not tail and self.isWord:
                return True

            return self.children[head].search(word[1:])

        return False

    def startsWith(self, prefix):
        """
        Returns if there is any word in the trie that starts with the given prefix.
        :type prefix: str (or list internally upon recursion)
        :rtype: bool
        """

        if not prefix:
            return True

        head, *tail = prefix

        if head in self.children:
            return self.children[head].startsWith(tail)

        return False

这是另一个使用集合模块中的'defaultdictionary'来利用'insert'函数中的递归的解决方案。

信用: https ://leetcode.com/problems/implement-trie-prefix-tree/discuss/631957/python-elegant-solution-no-nested-dictionaries

class Trie:

def __init__(self):
    """
    Initialize your data structure here.
    """
    self.nodes = collections.defaultdict(Trie)
    self.is_word = False

def insert(self, word: str) -> None:
    """
    Inserts a word into the trie.
    """
    if not word:
        self.is_word = True
    else:
        self.nodes[word[0]].insert(word[1:])
    

def search(self, word: str) -> bool:
    """
    Returns if the word is in the trie.
    """
    if not word:
        return self.is_word
    if word[0] in self.nodes:
        return self.nodes[word[0]].search(word[1:])
                
    return False
    
def startsWith(self, prefix: str) -> bool:
    """
    Returns if there is any word in the trie that starts with the given prefix.
    """
    if not prefix:
        return True
    
    if prefix[0] in self.nodes:
        return self.nodes[prefix[0]].startsWith(prefix[1:])
    
    return False

您的 Trie 对象将被实例化并按如下方式调用:

obj = Trie()
obj.insert(word)
param_2 = obj.search(word)
param_3 = obj.startsWith(prefix)
class TrieNode:
    def __init__(self):
        # each key is a TrieNode
        self.keys = {}
        self.end = False

class Trie:
    def __init__(self):
        self.root = TrieNode()
    # node=this.root gives error "this" is not defined
    def insert(self, word: str, node=None) -> None:
        if node == None:
            node = self.root
        # insertion is a recursive operation
        if len(word) == 0:
            node.end = True
            return
        elif word[0] not in node.keys:
            node.keys[word[0]] = TrieNode()
            self.insert(word[1:], node.keys[word[0]])
        # that means key exists
        else:
            self.insert(word[1:], node.keys[word[0]])
    def search(self, word: str, node=None) -> bool:
        if node == None:
            node = self.root
        # node.end=True means we have inserted the word before
        if len(word) == 0 and node.end == True:
            return True
        # if we inserted apple and then search for app we get false becase we never inserted app so a-p-p last_p.end is not True
        # But startsWith(app) would return True
        elif len(word) == 0:
            return False
        elif word[0] not in node.keys:
            return False
        else:
            # we have to return becasue api expects us to return bool
            return self.search(word[1:], node.keys[word[0]])

    def startsWith(self, prefix: str, node=None) -> bool:
        if node == None:
            node = self.root
        if len(prefix) == 0:
            return True
        elif prefix[0] not in node.keys:
            return False
        else:
            return self.startsWith(prefix[1:], node.keys[prefix[0]])

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM