当前位置: 首页 > article >正文

【leetcode】实现Tire(前缀树)

1、题目描述

Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补全和拼写检查。

请你实现 Trie 类:

  • Trie() 初始化前缀树对象。
  • void insert(String word) 向前缀树中插入字符串 word 。
  • boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false 。
  • boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false 。

2、初始思路

2.1 思路

在 Trie 树中,每个节点代表一个字符,并且可以有多个子节点,每个子节点代表下一个字符。由于本题只处理 小写英文字母(a-z),所以 Trie 树的每个节点最多有 26 个子节点,形成26 叉树

(1)首先定义树的节点:

class Node:
    _slots_ = 'son','end'
    def __init__(self):
        self.end = False
        self.son = {}

其中,_slot_的作用有两个,分别为:1、优化内存使用;2、限制动态属性添加。

(1)在处理insert时:

从 root 节点开始,逐个字符检查: 若 c 不在 cur.son 中,则新建一个 Node() 并添加到 cur.son[c];继续移动到 cur.son[c] 进行下一步处理;最后 cur.end = True,表示该路径上的最后一个节点是一个完整单词的结尾。

def insert(self, word: str) -> None:
    cur = self.root
    for c in word:
        if c not in cur.son:
            cur.son[c] = Node()
        cur = cur.son[c]
    cur.end = True  

插入 "apple" 过程如下:

root
 ├── 'a' -> Node
 │   ├── 'p' -> Node
 │   │   ├── 'p' -> Node
 │   │   │   ├── 'l' -> Node
 │   │   │   │   ├── 'e' -> Node(end=True)

而当插入“apple"后,再次插入”app“时,直接将最后一个字母"p”的end设置为True即可。插入后可显示为:

root
 ├── 'a' -> Node
 │   ├── 'p' -> Node
 │   │   ├── 'p' -> Node(end=True)
 │   │   │   ├── 'l' -> Node
 │   │   │   │   ├── 'e' -> Node(end=True)

(2)在定义search和startwith时,很明显可以使用同一个find函数,当查找到end=True时,满足search,此外,只要能找到字母,就满足startwith的要求。

def find(self, word: str) -> bool:
        cur = self.root
        for c in word:
            if c not in cur.son:
                return 0
            cur = cur.son[c]
        return 2 if cur.end else 1

    def search(self, word: str) -> bool:
        return self.find(word) == 2

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

2.2 完整代码

class Node:
    _slots_ = 'end', 'son'
    def __init__(self):
        self.son = {}
        self.end = False

class Trie:

    def __init__(self):
        self.root = Node()

    def insert(self, word: str) -> None:
        cur = self.root
        for c in word:
            if c not in cur.son:
                cur.son[c] = Node()
            cur = cur.son[c]
        cur.end = True
    
    def find(self, word: str) -> bool:
        cur = self.root
        for c in word:
            if c not in cur.son:
                return 0
            cur = cur.son[c]
        return 2 if cur.end else 1

    def search(self, word: str) -> bool:
        return self.find(word) == 2

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


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

http://www.kler.cn/a/572410.html

相关文章:

  • FastGPT 源码:基于 LLM 实现 Rerank (含Prompt)
  • android_viewtracker 原理
  • 【cuda学习日记】5.4 常量内存
  • leetcode383 赎金信
  • 【详解 | 辨析】“单跳多跳,单天线多天线,单信道多信道” 之间的对比
  • Git-cherry pick
  • 迷你世界脚本世界UI接口:UI
  • c++面试常见问题:虚表指针存在于内存哪个分区
  • Node.js学习分享(上)
  • python爬虫数据库概述
  • 【Java】IO流
  • Linux·数据库INSERT优化
  • PyTorch 与 NVIDIA GPU 的适配版本及安装
  • NO.23十六届蓝桥杯备战|二维数组|创建|初始化|遍历|memset(C++)
  • Kconfig与CMake初步模块化工程3
  • 刷题日记——部分二分算法题目分享
  • 我如何从 Java 和 Python 转向 Golang 的脚本和 GUI 工具开发
  • ThreadLocal解析
  • CTF 中的 XSS 攻击:原理、技巧与实战案例
  • 【Web前端开发】---HTML标签及标签属性