题目:
Implement a trie with insert, search, and startsWith methods.
Note:
You may assume that all inputs are consist of lowercase letters a-z.
分析:
对于一棵存储字单词的前缀树,是这样的:树的根结点是空的,其它非叶子节点中存储着一个字符,叶子节点是一个哨兵节点,用于表示它的父节点是一个单词的结尾字符,从根结点到任一叶子节点的路径上的节点构成一个完整单词。之所以叫前缀树,是因为有公共前缀的单词,在树中,它们的公共前缀由同一条路径表示。例如,存储bad、bat和good这三个单词的前缀树如下:
前缀树的实现代码如下:
package leetcode208;
import java.util.HashMap;
import java.util.Map;
public class TrieNode {
private Character key;
private Map<Character, TrieNode> children = new HashMap<>();
// 孩子节点包含SENTINEL的节点是单词的词尾字符
public static final TrieNode SENTINEL;
static {
SENTINEL = new TrieNode();
SENTINEL.setKey('$');
}
public TrieNode() {
}
public Character getKey() {
return key;
}
public void setKey(Character key) {
this.key = key;
}
public Map<Character, TrieNode> getChildren() {
return children;
}
public void setChildren(Map<Character, TrieNode> children) {
this.children = children;
}
public TrieNode getChild(char character) {
return this.children.get(character);
}
public void addChild(TrieNode child) {
this.children.put(child.getKey(), child);
}
public boolean containChild(TrieNode child) {
return children.containsValue(child);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((children == null) ? 0 : children.hashCode());
result = prime * result + ((key == null) ? 0 : key.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TrieNode other = (TrieNode) obj;
if (children == null) {
if (other.children != null)
return false;
} else if (!children.equals(other.children))
return false;
if (key == null) {
if (other.key != null)
return false;
} else if (!key.equals(other.key))
return false;
return true;
}
}
package leetcode208;
public class Trie {
private TrieNode root;
public Trie() {
root = TrieNode.SENTINEL;
}
// Inserts a word into the trie.
public void insert(String word) {
if (word == null || word.trim().length() == 0) {
return;
}
TrieNode cursor = root;
int len = word.length();
for(int i = 0; i < len; i++) {
Character temp = word.charAt(i);
TrieNode child = cursor.getChild(temp);
if (child == null) {
child = new TrieNode();
child.setKey(temp);
cursor.addChild(child);
}
cursor = child;
}
cursor.addChild(TrieNode.SENTINEL);
}
// Returns if the word is in the trie.
public boolean search(String word) {
if (word == null || word.length() == 0) {
return false;
}
TrieNode cursor = root;
int len = word.length();
for(int i = 0; i < len; i++) {
Character temp = word.charAt(i);
TrieNode child = cursor.getChild(temp);
if (child == null) {
return false;
}
cursor = child;
}
if (!cursor.containChild(TrieNode.SENTINEL)) {
return false;
}
return true;
}
// Returns if there is any word in the trie
// that starts with the given prefix.
public boolean startsWith(String prefix) {
if (prefix == null || prefix.length() == 0) {
return false;
}
TrieNode cursor = root;
int len = prefix.length();
for(int i = 0; i < len; i++) {
Character temp = prefix.charAt(i);
TrieNode child = cursor.getChild(temp);
if (child == null) {
return false;
}
cursor = child;
}
return true;
}
}
package leetcode208;
public class LeetCode208 {
public static void main(String[] args) {
Trie trie = new Trie();
trie.insert("ab");
System.out.println(trie.search("a"));
System.out.println(trie.startsWith("a"));
}
}