208. 实现 Trie (前缀树) 中等
实现一个 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
构成的。 - 保证所有输入均为非空字符串。
class Trie {
private TrieNode root;
public Trie() {
root = new TrieNode();
}
/**
* 向 Trie 树中插入键
* 我们通过搜索 Trie 树来插入一个键。我们从根开始搜索它对应于第一个键字符的链接。有两种情况:
* 链接存在。沿着链接移动到树的下一个子层。算法继续搜索下一个键字符。
* 链接不存在。创建一个新的节点,并将它与父节点的链接相连,该链接与当前的键字符相匹配。
* 重复以上步骤,直到到达键的最后一个字符,然后将当前节点标记为结束节点,算法完成。
*/
public void insert(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
char currentChar = word.charAt(i);
if (!node.containsKey(currentChar)) {
node.put(currentChar, new TrieNode());
}
node = node.get(currentChar);
}
node.setEnd();
}
/**
* 在 Trie 树中查找键
* 每个键在 trie 中表示为从根到内部节点或叶的路径。我们用第一个键字符从根开始。检查当前节点中与键字符对应的链接。有两种情况:
* 存在链接。我们移动到该链接后面路径中的下一个节点,并继续搜索下一个键字符。
* 不存在链接。若已无键字符,且当前结点标记为 isEnd,则返回 true。否则有两种可能,均返回 false :
* 还有键字符剩余,但无法跟随 Trie 树的键路径,找不到键。
* 没有键字符剩余,但当前结点没有标记为 isEnd。也就是说,待查找键只是Trie树中另一个键的前缀。
*/
private TrieNode searchPrefix(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
char currentChar = word.charAt(i);
if (node.containsKey(currentChar)) {
node = node.get(currentChar);
} else {
return null;
}
}
return node;
}
public boolean search(String word) {
TrieNode node = searchPrefix(word);
return node != null && node.isEnd();
}
public boolean startsWith(String prefix) {
TrieNode node = searchPrefix(prefix);
return node != null;
}
/**
* Trie 树的结点结构
* 最多 R 个指向子结点的链接,其中每个链接对应字母表数据集中的一个字母。
* 假定 R 为 26,小写拉丁字母的数量。
* 布尔字段,以指定节点是对应键的结尾还是只是键前缀。
*/
class TrieNode {
private TrieNode[] nodes;
private boolean isEnd;
private final int R = 26;
public TrieNode() {
nodes = new TrieNode[R];
}
public boolean containsKey(char ch) {
return nodes[ch - 'a'] != null;
}
public TrieNode get(char ch) {
return nodes[ch - 'a'];
}
public void put(char ch, TrieNode node) {
nodes[ch - 'a'] = node;
}
public void setEnd() {
isEnd = true;
}
public boolean isEnd() {
return isEnd;
}
}
}
应用:自动补全 拼音检查 IP路由(最长前缀匹配) T9 (九宫格)打字预测 单词游戏