Leetcode 208:实现Trie(前缀树)

问题描述:

思路简述:

借用一张图

image.png

前缀树又叫做单词查找树,是一种树形数据结构,可以用于存储大量的字符串,优点是可以利用不同字符串的公共前缀来节省大量的存储空间,避免了顺序存储字符串列表的冗余,可以看成是一个二十六叉树,一个子节点对应的就是二十六个字母中的一个,下面给出前缀树中一个节点的数据结构(以Python为例):

class TrieNode:
    def __init__(self):
        self.isWord = True # 是否是单词
        self.children = [0] * 26

每个节点维护两个信息,一个是子节点的一个列表,一个是标识当前节点构成的字符串是否是存储的字符串,下面用一个实际例子来说明:

1、构造前缀树:

假设当前前缀树为空,即只有一个根节点,现在要向前缀树中插入字符串,比如"chen"字符串,则对该字符串按单字符进行遍历,因为当前前缀树为空,所以四个节点应该会被创建,得到的结果即:

除了最后一个“N”节点中isWord = True(表示“N”节点及之前的所有节点构成的字符为一个存储的字符串),其他节点的该属性都应该为False(表示并没有构成字符串)。

2、插入字符串

现在得到了存储了"chen"字符串的前缀树,如果要继续插入另一个字符串"chan",可以看到这个字符串与之前已经存储了的"chen"有相同的前缀"ch",在插入时也是先按字符对“chan”字符串遍历,第一个字符'c'发现在根节点的children中存在这个子节点,于是直接复用这个字符,再继续发现字符'h'也是存在于'c'节点的子节点中的,于是又复用这个'h'节点,直到判断'h'节点的子节点,没有发现'a'节点,这时候才会去新建节点,插入完成后得到的前缀树如图:

3、查找字符串

在前缀树中查找字符串是否存在也很简单,比如要查找"chan"是否存在,先从根节点开始,先判断根节点的children中'c'是否存在,如果存在则判断'c'节点的children中'h'是否存在 。。。 。。。

整个过程中只要有一个字符不存在,则可以直接认为前缀树中不存在该字符串,如果所有节点都存在,还应该判断最终的节点的isWord是否为True,如果为False也应当认为前缀树中不存在该字符串,因为如果前缀树中存储的"helloworld"字符串,查找的"hello",则一定也能够查找到,但这时候'o'节点的isWord是为False的,所以也不能认为它存储了我们要查找的字符串。

有了这样的前置知识这道题就非常简单了。

代码实现:

class TrieNode:
    def __init__(self):
        self.isWord = True # 是否是单词
        self.children = [0] * 26

class Trie:
    def __init__(self):
        self.root = TrieNode()

    def find(self, word:str) -> TrieNode:
        current = self.root
        for w in word:
            index = ord(w) - ord('a')
            if current.children[index] == 0:
                return None
            current = current.children[index]
        return current

    def insert(self, word: str) -> None:
        current = self.root
        for w in word:
            index = ord(w) - ord('a')
            if current.children[index] == 0:
                current.children[index] = TrieNode()
                current.children[index].isWord = False
            current = current.children[index]
        current.isWord = True
            

    def search(self, word: str) -> bool:
        current = self.find(word)
        return current!=None and current.isWord



    def startsWith(self, prefix: str) -> bool:
        return self.find(prefix)!=None

注:在search和startswith方法中,都需要对前缀树查找,可以抽取一个公共方法find()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值