Description
A trie (pronounced as “try”) or prefix tree is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker.
Implement the Trie class:
- Trie() Initializes the trie object.
- void insert(String word) Inserts the string word into the trie.
- boolean search(String word) Returns true if the string word is in the trie (i.e., was inserted before), and false otherwise.
- boolean startsWith(String prefix) Returns true if there is a previously inserted string word that has the prefix prefix, and false otherwise.
Examples
Example 1:
Input
[“Trie”, “insert”, “search”, “search”, “startsWith”, “insert”, “search”]
[[], [“apply”], [“apply”], [“app”], [“app”], [“app”], [“app”]]
Output
[null, null, true, false, true, null, true]
Explanation
Trie trie = new Trie();
trie.insert(“apply”);
trie.search(“apply”); // return True
trie.search(“app”); // return False
trie.startsWith(“app”); // return True
trie.insert(“app”);
trie.search(“app”); // return True
Constraints:
1 <= word.length, prefix.length <= 2000
word and prefix consist only of lowercase English letters.
At most 3 * 104 calls in total will be made to insert, search, and startsWith.
解题思路
题目已经明确给出了==(prefix tree)==,就是让人构建前缀树
前缀树虽然构建的时候较为耗时,但对于查询有较高的处理效率
前缀树顾名思义就是一个树结构,每个单词都是从root开始到end的一条路径,我这里以example1为例,看一下前缀树的构建和查询流程
首先是insert “apply”
要注意的是y后面要接一个end,证明这个到这里才是一个完整的单词
然后是查询apply
结果有end,查询成功
再来是查询app
对应的p处没有end标识,所以虽然有该路径,但是没有对应单词
再insert app
就可以了!
代码
class TreeNode{
public List<TreeNode> children;
public char value;
public TreeNode(char v){
value = v;
children = new ArrayList<>();
}
public TreeNode(char v, List<TreeNode> nodes){
value = v;
children = new ArrayList<>(nodes);
}
}
class Trie {
public void addChild(TreeNode node, TreeNode addition){
node.children.add(addition);
}
public void addChild(TreeNode node, char c){
TreeNode addition = new TreeNode(c);
node.children.add(addition);
}
public TreeNode creates(TreeNode root, char c){
for(TreeNode node: root.children){
if(node.value == c)
return node;
}
TreeNode node = new TreeNode(c);
addChild(root, node);
return node;
}
public TreeNode contains(TreeNode root, char c){
for(TreeNode node: root.children){
if(node.value == c)
return node;
}
return null;
}
private TreeNode root;
/** Initialize your data structure here. */
public Trie() {
root = new TreeNode('A');
}
/** Inserts a word into the trie. */
public void insert(String word) {
TreeNode node = root;
for(int i = 0; i < word.length(); i++){
char currentChar = word.charAt(i);
node = creates(node, currentChar);
}
creates(node, 'E');
}
/** Returns if the word is in the trie. */
public boolean search(String word) {
TreeNode node = root;
for(int i = 0; i < word.length(); i++){
char currentChar = word.charAt(i);
node = contains(node, currentChar);
if(node == null)
return false;
}
TreeNode answerNode = contains(node, 'E');
return answerNode != null;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
public boolean startsWith(String prefix) {
TreeNode node = root;
for(int i = 0; i < prefix.length(); i++){
char currentChar = prefix.charAt(i);
node = contains(node, currentChar);
if(node == null)
return false;
}
return true;
}
}
/**
* 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);
*/