题目描述
思路解析动画文字版
下面 9 步动画会按主解代码推进,而不是泛泛讲题型。
insert("app") · 按字符建一条路径:insert("app"):逐字符建一条路径 root→a→p→p。末位 p2 打上「词尾」标记(绿色 done),表示「app 是一个完整单词」。
insert("apple") · 公共前缀直接复用:insert("apple"):前三位 app 复用已有节点(不重建),只新建 l、e。末位 e 也标词尾(绿色 done)。这就是 Trie 共享前缀省空间的关键。
search("app") · 走到底且是词尾 → true:search("app"):沿 a→p→p 走到末位 p2,它是绿色词尾节点 → 是完整单词 → 返回 true。
search("ap") · 路径在但不是词尾 → false:search("ap"):走到 p1 停下(高亮的当前节点),它不是绿色词尾;真正的词尾是它后面的 p2(绿)。所以 "ap" 不是完整单词 → 返回 false。
startsWith("ap") · 只看路径在不在 → true:startsWith("ap"):和上一步走到完全相同的 p1,但这次只问「路径走得通吗」——能走到就行,不看后面 p2 是不是绿色词尾 → 返回 true。search 与 startsWith 唯一的区别就在这里。
记住这题的代码骨架:题意约束先落到状态变量,再用循环或递归维护它。
迁移阶梯:把这题练到能复述后,再去同类题里迁移:先复用状态定义,再调整边界条件。
边界三连:边界三连:极端输入先过一遍。
几个高频追问,记住答法。
参考代码
class Trie: def __init__(self): self.root = {} def insert(self, word): node = self.root for ch in word: node = node.setdefault(ch, {}) node['#'] = True def search(self, word): node = self.root for ch in word: if ch not in node: return False node = node[ch] return '#' in node def startsWith(self, prefix): node = self.root for ch in prefix: if ch not in node: return False node = node[ch] return True复杂度
- 时间复杂度:O(L),L 为单词或前缀长度
- 空间复杂度:O(total chars),保存前缀树节点
易错点
面试追问把动画讲成自己的话
追问insert/search/startsWith 复杂度?
追问Trie 比哈希集合好在哪?
追问空间消耗多少?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
添加与搜索单词 - 数据结构设计
LeetCode 211 · 中等 · 沿着 字典树 Trie 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题