题目
Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补全和拼写检查。
请你实现 Trie 类:
- Trie() 初始化前缀树对象。
- void insert(String word) 向前缀树中插入字符串 word 。
- boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false 。
- boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false 。
示例:
输入
"Trie", "insert", "search", "search", "startsWith", "insert", "search"
\[\], \["apple"\], \["apple"\], \["app"\], \["app"\], \["app"\], \["app"\]
输出
null, null, true, false, true, null, true
解释
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
题解
java
class Trie {
private static class Node {
Node[] son = new Node[26];
boolean end = false;
}
private final Node root = new Node();
public void insert(String word) {
Node cur = root;
for (char c : word.toCharArray()) {
c -= 'a';
if (cur.son[c] == null) { // 无路可走?
cur.son[c] = new Node(); // new 出来!
}
cur = cur.son[c];
}
cur.end = true;
}
public boolean search(String word) {
return find(word) == 2;
}
public boolean startsWith(String prefix) {
return find(prefix) != 0;
}
private int find(String word) {
Node cur = root;
for (char c : word.toCharArray()) {
c -= 'a';
if (cur.son[c] == null) { // 道不同,不相为谋
return 0;
}
cur = cur.son[c];
}
// 走过同样的路(2=完全匹配,1=前缀匹配)
return cur.end ? 2 : 1;
}
}
/**
* Your Trie object will be instantiated and called as such:
* Trie obj = new Trie();
* obj.insert(word);
* boolean param_2 = obj.search(word);
* boolean param_3 = obj.startsWith(prefix);
*/
解析
出自:灵茶山艾府:从二叉树到二十六叉树(Python/Java/C++/C/Go/JS/Rust)
- private static class Node {Node[] son = new Node[26]; boolean end = false;}: 定义了一个内部类 Node,它是 Trie 的节点结构。son 是一个数组,存储了该节点的子节点;end 用于标识一个单词在此处结束(即该路径在单词字典中形成了一个完整的单词)。
- private final Node root = new Node();: 创建根节点,并初始化为一个新的 Node 对象。这个根节点的所有子节点都将作为 Trie 树的起始位置。
- 3-5: insert 方法用于向 Trie 中插入字符串 word。它通过遍历 word 中的每个字符来工作,如果当前字符对应的 son 数组索引为 null,就创建一个新的 Node(即初始化该子节点)。最后将单词标记为结束。
- 6-8: search 方法用于在 Trie 中查找给定的字符串 word。如果 find 返回的结果是表示完全匹配且该路径结束的 2,则返回 true;否则返回 false。
- 9-10: startsWith 方法用于检查是否有任何单词以给定前缀 prefix 开头。如果 find 返回的结果不是表示没有对应字符的路径(即对应索引在 son 数组中不为空),则返回 true;否则返回 false。
- 11-20: find 方法用于找出给定的 word。它遍历 word 中的每个字符并尝试从根节点沿着路径向下移动到子树,直到达到单词的末尾或遇到不存在于 Trie 中的字符。如果单词在这个位置结束(end = true)并且找到了对应索引在 son 数组中的节点,返回2;否则表示没有完全匹配且该路径的前缀在此处终止,返回1。
- /**
Your Trie object will be instantiated and called as such:
Trie obj = new Trie();
obj.insert(word);
boolean param_2 = obj.search(word);
boolean param_3 = obj.startsWith(prefix);
*/
等价代码用于创建一个新的 Trie,插入单词、搜索单词和检查是否存在以某个前缀开头的单词。实例化的 Trie 对象用于执行这些操作。这个类主要用于快速查找、删除和插入数据结构。