Algorithms first
实现 Trie (前缀树) · 交互式算法学习
实现 Trie 的插入、完整词搜索和前缀搜索。
#208 · 字典树
实现 Trie (前缀树)
Implement Trie (Prefix Tree)
insert apple; search apple; startsWith app树 / 图8 个关键状态
步骤 1从空的根节点开始插入 apple。
node=root推荐
前缀树节点
时间
每次 O(L)空间 O(总字符)每个字符是一条边,节点标记是否为完整词结尾。
1class Trie {2 constructor() {3 this.root = {}4 }5 insert(w) {6 let n = this.root;7 for (const c of w) n = n[c] ??= {};8 n.end = true9 }10 walk(w) {11 let n = this.root;12 for (const c of w) {13 n = n[c];14 if (!n) return null15 }16 return n17 }18 search(w) {19 return !!this.walk(w)?.end20 }21 startsWith(p) {22 return !!this.walk(p)23 }24}多语言参考
来源 · CC BY-SA 4.0 ↗Java · C++ · Go
这是一组同题正确实现,独立于上方当前动画方法;不同语言可能采用另一种正确策略。
1class Trie {2 private Trie[] children;3 private boolean isEnd;4 5 public Trie() {6 children = new Trie[26];7 }8 9 public void insert(String word) {10 Trie node = this;11 for (char c : word.toCharArray()) {12 int idx = c - 'a';13 if (node.children[idx] == null) {14 node.children[idx] = new Trie();15 }16 node = node.children[idx];17 }18 node.isEnd = true;19 }20 21 public boolean search(String word) {22 Trie node = searchPrefix(word);23 return node != null && node.isEnd;24 }25 26 public boolean startsWith(String prefix) {27 Trie node = searchPrefix(prefix);28 return node != null;29 }30 31 private Trie searchPrefix(String s) {32 Trie node = this;33 for (char c : s.toCharArray()) {34 int idx = c - 'a';35 if (node.children[idx] == null) {36 return null;37 }38 node = node.children[idx];39 }40 return node;41 }42}43 44/**45 * Your Trie object will be instantiated and called as such:46 * Trie obj = new Trie();47 * obj.insert(word);48 * boolean param_2 = obj.search(word);49 * boolean param_3 = obj.startsWith(prefix);50 */交互式算法学习
从执行步骤真正理解 LeetCode 经典 150
本站整理 150 道高频算法面试题和 302 种解法。动画方法同步展示 JavaScript 与 Python;每题另提供 Java、C++ 与 Go 同题参考实现。
AlgoViz Lab
实现 Trie (前缀树) · 解法对比
实现 Trie 的插入、完整词搜索和前缀搜索。
- 测试用例
insert apple; search apple; startsWith app- 题目分类
- 字典树
- 解法对比
- 2
字符串集合扫描前缀
完整词放 Set;前缀查询扫描所有词。
- 时间
startsWith O(NL)- 空间
O(总字符)
前缀树节点
每个字符是一条边,节点标记是否为完整词结尾。
- 时间
每次 O(L)- 空间
O(总字符)
为什么有效
把公共前缀共享为同一条路径。完整单词查询需要到达末节点并检查结束标记,前缀查询只需路径存在。
关键不变量
walk 每消费一个字符,当前节点就代表已经消费的整个前缀。
易错点
- search 与 startsWith 的区别是是否检查结束标记。
- 插入短词后仍要允许更长词继续复用其路径。
边界情况
- 空前缀通常存在。
- 插入同一单词多次不应破坏结构。
- 一个单词可以是另一个单词的前缀。
更多案例
insert(apple), search(apple), startsWith(app)true, trueapple 路径存在且末节点有结束标记。
insert(apple), search(app)falseapp 是前缀但尚未作为完整单词插入。
insert(app), search(app)true标记第二个 p 为单词结尾。