Leetcode Python208。实现特里(前缀树)

时间:2018-10-28 19:23:53

标签: python algorithm recursion data-structures trie

有人可以说我的代码有什么问题吗,当我下载特定的测试用例时,除了最后一个测试用例,它都通过了所有测试用例,预期和实际输出看起来都一样,问题是https://leetcode.com/problems/implement-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

谢谢。

2 个答案:

答案 0 :(得分:0)

我注意到的一个怪癖是将空前缀传递到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

答案 1 :(得分:0)

这是另一种使用集合模块中的“defaultdictionary”来利用“插入”函数中的递归的解决方案。

信用: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)