Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。
典型应用是
1. 用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。
2. 用于前缀匹配,比如我们在搜索引擎中输入待搜索的字词时,搜索引擎会给予提示有哪些前缀。
它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。缺点就是空间开销大。
前缀树
有如下特点:
1. 根节点不包含字符,除根节点外每一个节点都只包含一个字符。
2. 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
3. 每个节点的所有子节点包含的字符都不相同。
4. 如果字符的种数为n,则每个结点的出度为n,这也是空间换时间的体现,浪费了很多的空间。
5. 插入查找的复杂度为O(n),n为字符串长度。
对于该题,因为只存储小写英文字母,因此,每个节点设置一个容量为26的数组即可,索引index=c-’a'。
对于insert操作:依次判断word中的每个字母c的位置,检索第index个数组的内容,如果为null,则新建一个节点(表示该处有字母c),如果不为空,则更新c,从此处继续判断下一个位置。每插入完成一个word,最后一个字母的isEndOfword为true。
对于search操作:确定每个字母的index,依次向下查找,结束时isEndOfword为true。
对于startsWith操作:在search操作的基础上,结束时isEndOfword的值可以为false。
class Trie {
private static final int kAlphabetCount = 26;
class TrieNode {
TrieNode[] children = new TrieNode[kAlphabetCount];
boolean isEndOfWord = false;
}
private TrieNode root = new TrieNode();
public void insert(String word) {
TrieNode current = root;
for(char ch: word.toCharArray()) {
int index = ch - 'a';
if(current.children[index] == null) {
current.children[index] = new TrieNode();
}
current = current.children[index];
}
current.isEndOfWord = true;
}
public boolean search(String word) {
TrieNode current = root;
for(char ch: word.toCharArray()) {
int index = ch - 'a';
if(current.children[index] == null) {
return false;
}
current = current.children[index];
}
return current != null && current.isEndOfWord;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
public boolean startsWith(String prefix) {
TrieNode current = root;
for(char ch: prefix.toCharArray()) {
int index = ch - 'a';
if(current.children[index] == null) {
return false;
}
current = current.children[index];
}
return current != 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);
*/