LeetCode Hot100(39/100)——208. 实现 Trie (前缀树)

文章目录

✅ 题目链接:LeetCode - Implement Trie (Prefix Tree)

难度:中等

适合人群:掌握数据结构基础、希望理解字符串搜索机制的开发者


一、题目描述

实现一个 前缀树(Trie),支持以下三种操作:

  1. insert(word):插入一个单词。
  2. search(word):判断单词是否存在。
  3. startsWith(prefix):判断是否存在某个单词以给定前缀开始。

示例输入与输出:

text 复制代码
输入:
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple");   // 返回 true
trie.search("app");     // 返回 false
trie.startsWith("app"); // 返回 true
trie.insert("app");
trie.search("app");     // 返回 true

二、问题分析

Trie 是一种用于 高效存储和查找字符串集合 的数据结构。

它的核心思想是将字符串以「公共前缀」的方式组织在一棵树中,避免重复存储。

Trie 结构示意图

Root
a
p
l
e
b
t

在上图中,我们插入了 "apple"、"app"、"bat" 三个单词。

可见 "app" 是 "apple" 的前缀,两者共享节点,从而节省存储空间。


三、设计思路

节点结构(TrieNode)

  • 每个节点包含:
    • children:保存连接到下一个字符的节点(通常用数组或哈希表)。
    • isEnd:标记当前节点是否为某个单词的结尾。

Trie 的核心操作流程

1. 插入单词 insert(word)

否
是
否
是
开始
取根节点
当前字符是否存在?
创建新节点
进入下一个节点
是否到达末尾?
标记 isEnd=true
结束

2. 查找单词 search(word)

逐字符遍历节点:

  • 若某个字符路径不存在,返回 false
  • 若遍历完成且最终节点 isEnd == true,返回 true
3. 前缀匹配 startsWith(prefix)

与 search 类似,但不关心 isEnd,只需所有前缀节点存在即可返回 true


四、复杂度分析

操作 时间复杂度 空间复杂度 说明
insert O(L) O(L * α) L为单词长度,α为字母表大小(如26)
search O(L) O(1) 遍历字符路径
startsWith O(L) O(1) 仅检查前缀存在

由于 Trie 节点彼此共享公共前缀,它在存储大量相似单词时效率极高。


五、Java 实现代码

下面给出基于数组结构的 Java 实现,结构清晰,性能稳定:

java 复制代码
class TrieNode {
    TrieNode[] children;
    boolean isEnd;

    public TrieNode() {
        children = new TrieNode[26];
        isEnd = false;
    }
}

public class Trie {
    private TrieNode root;

    public Trie() {
        root = new TrieNode();
    }

    // 插入单词
    public void insert(String word) {
        TrieNode node = root;
        for (char c : word.toCharArray()) {
            int index = c - 'a';
            if (node.children[index] == null) {
                node.children[index] = new TrieNode();
            }
            node = node.children[index];
        }
        node.isEnd = true;
    }

    // 搜索完整单词
    public boolean search(String word) {
        TrieNode node = find(word);
        return node != null && node.isEnd;
    }

    // 判断是否存在以指定前缀开始的单词
    public boolean startsWith(String prefix) {
        TrieNode node = find(prefix);
        return node != null;
    }

    // 辅助函数:根据字符串查找节点
    private TrieNode find(String prefix) {
        TrieNode node = root;
        for (char c : prefix.toCharArray()) {
            int index = c - 'a';
            if (node.children[index] == null) {
                return null;
            }
            node = node.children[index];
        }
        return node;
    }
}

六、运行示意图(时序图)

TrieNode Trie User TrieNode Trie User insert("apple") 为每个字符创建节点 a ->> p ->> p ->> l ->> e 返回最后节点 插入完成 search("app") 查找 a ->> p ->> p 查找结束 返回 false(未标为结束) startsWith("app") 查找前缀路径 前缀存在 返回 true


七、优化与扩展

  • 可扩展字符集: 如果需要支持 Unicode 或大小写混合,可以将 children 改为 Map<Character, TrieNode>。
  • 删除操作: 可通过递归方式实现,当某节点无其他分支且非单词结尾时可清理。
  • 前缀搜索应用: 如自动补全、词频统计等。

Trie 是一种非常有价值的数据结构,在 搜索引擎自动补全、拼写校验、字符串匹配 等场景中广泛应用。

其核心优势在于 以空间换时间,在字符层级组织信息,快速定位前缀路径。

相关推荐
UIU11411 小时前
P1233 [ICPC 2001 Taejon R] 木棍加工
数据结构·c++·算法·动态规划
论文复现现场11 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
ZhengEnCi11 小时前
用 AI 写代码为什么拼到最后还是拼人:算力瓶颈与领域专家提示词的本质差异
算法·架构
秋天的怀念_David12 小时前
第二十一夜 · 数字黑洞与西西弗斯的惩罚
java·程序人生·算法
碧海银沙音频科技研究院13 小时前
在PC电脑上用Whisper→Marian算法实现离线语音翻译功能
算法·whisper
niyongsheng13 小时前
3D 装箱算法工程化:数据结构、放置启发式与支撑规则
数据结构·算法·rust
j7~16 小时前
【穷举、深搜与回溯算法】一棵决策树讲透全排列与子集
数据结构·c++·算法·leetcode·回溯·递归
傅科摆 _ py17 小时前
DP,贪心,堆和栈,二分力扣复习
开发语言·python·算法
Shaoshing17 小时前
LeetCode100 42.接雨水
java·算法·leetcode
域限奇点访客18 小时前
用AI生成问卷的网站怎么选?看题目录入结构、题型映射和生成后的校验
算法