关注
文末的名片达文汐
,回复关键词“力扣源码”,即可获取完整源码!!详见:源码和核心代码的区别
题目详情
实现一个 Trie(前缀树),包含以下操作:
Trie()
初始化前缀树对象。void insert(String word)
向前缀树中插入字符串word
。boolean search(String word)
如果字符串word
在前缀树中,返回true
;否则,返回false
。boolean startsWith(String prefix)
如果之前插入的字符串包含前缀prefix
,返回true
;否则,返回false
。
示例:
输入:
[“Trie”, “insert”, “search”, “search”, “startsWith”, “insert”, “search”]
[[], [“apple”], [“apple”], [“app”], [“app”], [“app”], [“app”]]
输出:
[null, null, true, false, true, null, true]
提示:
1 <= word.length, prefix.length <= 2000
word
和prefix
仅由小写英文字母组成insert
、search
和startsWith
调用次数总计不超过 (3 \times 10^4)
解题思路
-
数据结构设计:
- 每个节点(
TrieNode
)包含一个长度为 26 的子节点数组(对应 26 个小写字母)和一个布尔值isEnd
,标记该节点是否为某个单词的结尾。 - 根节点不存储字符,从根节点的子节点开始存储。
- 每个节点(
-
插入操作:
- 从根节点开始遍历每个字符:
- 若当前字符对应的子节点不存在,则新建节点。
- 将指针移动到子节点。
- 遍历完成后,将最后一个节点的
isEnd
标记为true
。
- 从根节点开始遍历每个字符:
-
搜索操作:
- 从根节点开始遍历每个字符:
- 若当前字符对应的子节点不存在,返回
false
。 - 将指针移动到子节点。
- 若当前字符对应的子节点不存在,返回
- 遍历完成后,检查最后一个节点的
isEnd
是否为true
。
- 从根节点开始遍历每个字符:
-
前缀匹配操作:
- 与搜索操作类似,但无需检查最后一个节点的
isEnd
标记,只需确保所有字符的路径存在。
- 与搜索操作类似,但无需检查最后一个节点的
代码实现(Java版)
class Trie {
// 定义节点类
static class TrieNode {
TrieNode[] children;
boolean isEnd;
public TrieNode() {
children = new TrieNode[26]; // 26个小写字母
isEnd = false;
}
}
private final 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 = root;
for (char c : word.toCharArray()) {
int index = c - 'a';
if (node.children[index] == null) {
return false; // 路径不存在
}
node = node.children[index];
}
return node.isEnd; // 检查是否为单词结尾
}
public boolean startsWith(String prefix) {
TrieNode node = root;
for (char c : prefix.toCharArray()) {
int index = c - 'a';
if (node.children[index] == null) {
return false; // 路径不存在
}
node = node.children[index];
}
return true; // 前缀路径存在即可
}
}
代码说明
-
节点结构:
TrieNode
包含一个长度为 26 的数组children
,存储子节点。isEnd
标记当前节点是否为单词的结尾。
-
插入逻辑:
- 遍历单词字符,逐层创建或访问子节点。
- 在单词末尾设置
isEnd = true
。
-
搜索逻辑:
- 遍历单词字符,若路径中断则返回
false
。 - 最终检查
isEnd
确保是完整单词。
- 遍历单词字符,若路径中断则返回
-
前缀匹配逻辑:
- 仅需验证路径是否存在,无需检查
isEnd
。
- 仅需验证路径是否存在,无需检查