题目描述
实现一个 Trie
(前缀树),包含 insert
, search
, 和 startsWith
这三个操作。
样例
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
说明:
- 你可以假设所有的输入都是由小写字母
a-z
构成的。 - 保证所有输入均为非空字符串。
算法分析
字典树问题
- 1、先定义一个结构点表示某一个树的某一个结点,
is_end
表示从根结点到该位置是否存在有一个单词,该节点有26
个儿子,分别对应'a'
到'z'
- 2、
insert()
操作,从根结点出发,沿着字符串的字符一直往下走,若某一字符不存在,则直接把它创建出来,继续走下去,走完了整个单词,标记最后的位置的is_end = true
- 3、
search()
操作,从根结点出发,沿着字符串的字符一直往下走,若某一字符不存在,则直接return false
,当很顺利走到最后的位置的时候,判断最后一个位置的is_end
即可
时间复杂度 $O(n)$
n
表示单词操作字符串长度
Java 代码
class Trie {
Node root;
/** Initialize your data structure here. */
public Trie() {
root = new Node();
}
/** Inserts a word into the trie. */
public void insert(String word) {
Node p = root;
for(int i = 0;i < word.length();i ++)
{
int u = word.charAt(i) - 'a';
//如果p这个节点不存在这个儿子,则把它创建出来(有路就直接走,没有路搭个桥都要走过去)
if(p.son[u] == null) p.son[u] = new Node();
p = p.son[u];
}
p.is_end = true;
}
/** Returns if the word is in the trie. */
public boolean search(String word) {
Node p = root;
for(int i = 0;i < word.length();i ++)
{
int u = word.charAt(i) - 'a';
if(p.son[u] == null) return false;
p = p.son[u];
}
return p.is_end;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
public boolean startsWith(String prefix) {
Node p = root;
for(int i = 0;i < prefix.length();i ++)
{
int u = prefix.charAt(i) - 'a';
if(p.son[u] == null) return false;
p = p.son[u];
}
return true;
}
}
class Node
{
boolean is_end;
Node[] son = new Node[26];
Node()
{
is_end = false;
for(int i = 0;i < 26;i ++)
son[i] = null;
}
}
/**
* 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);
*/