力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
public class Trie {
public class TireNode {
private int level; // 所在层级
private boolean end; // 是否为词尾
private HashMap<Character, TireNode> nextChs; // 后续所有词节点
TireNode(int level, boolean end) {
this.level = level;
this.end = end;
}
// 插入下一几点
public TireNode putNext(char ch, boolean end) {
TireNode newNode = new TireNode(this.level + 1, end);
if (this.nextChs == null) this.nextChs = new HashMap<>();
this.nextChs.put(ch, newNode);
return newNode;
}
}
private TireNode root;
public Trie() {
// 初始化一个根节点
root = new TireNode(-1, false);
}
public void insert(String word) {
TireNode node = match(word);
for (int i = node.level + 1; i < word.length(); i++) {
node = node.putNext(word.charAt(i), i == word.length() - 1);
}
// 这个一定要加上,因为插入词的所有字符可能都存在树里,但是作为另外某些词的一部分。
node.end = true;
}
public boolean search(String word) {
TireNode node = match(word);
// 判断匹配的节点层级是否为词尾,并且此节点为词尾节点。
return node.level == word.length() - 1 && node.end == true;
}
public boolean startsWith(String prefix) {
TireNode node = match(prefix);
// 判断匹配的节点层级是否为词尾
return node.level == prefix.length() - 1;
}
// 这是插入和查找等函数的关键基础函数,通过词查找最大匹配的节点
private TireNode match(String word) {
TireNode node = root;
char ch;
for (int i = 0; i < word.length(); i++) {
ch = word.charAt(i);
if (node.nextChs != null && node.nextChs.containsKey(ch)) {
node = node.nextChs.get(ch);
} else
break;
}
return node;
}
public static void main(String[] args) {
Trie trie = new Trie();
trie.insert("apple");
boolean result = trie.search("apple"); // 返回 True
System.out.println("result = " + result);
result = trie.search("app"); // 返回 False
System.out.println("result = " + result);
result = trie.startsWith("app"); // 返回 True
System.out.println("result = " + result);
trie.insert("app");
result = trie.search("app"); // 返回 True
System.out.println("result = " + result);
}
public class TireNode {
private int level; // 所在层级
private boolean end; // 是否为词尾
private HashMap<Character, TireNode> nextChs; // 后续所有词节点
TireNode(int level, boolean end) {
this.level = level;
this.end = end;
}
// 插入下一几点
public TireNode putNext(char ch, boolean end) {
TireNode newNode = new TireNode(this.level + 1, end);
if (this.nextChs == null) this.nextChs = new HashMap<>();
this.nextChs.put(ch, newNode);
return newNode;
}
}
1 字符所在层级level变量的设计:因为词的匹配不光要字符相同,位置也要一样;
word
?在前缀树,是否存在前缀为某个字符串的词,都可以复用这个函数 // 这是插入和查找等函数的关键基础函数,通过词查找最大匹配的节点
private TireNode match(String word) {
TireNode node = root;
char ch;
for (int i = 0; i < word.length(); i++) {
ch = word.charAt(i);
if (node.nextChs != null && node.nextChs.containsKey(ch)) {
node = node.nextChs.get(ch);
} else
break;
}
return node
}
Trie()
?初始化前缀树对象:因为所有词没有统一的根字符,创建一个虚拟的空的根节点 // 初始化一个根节点
root = new TireNode(-1, false);
编写函数void insert(String word)
?向前缀树中插入字符串?word
?,首先在前缀树中查找与word最深匹配的节点,然后再将后续字符一一插入树中,最后将词尾字符所在节点的end值设置为true public void insert(String word) {
TireNode node = match(word);
for (int i = node.level + 1; i < word.length(); i++) {
node = node.putNext(word.charAt(i), i == word.length() - 1);
}
// 这个一定要加上,因为插入词的所有字符可能都存在树里,但是作为另外某些词的一部分。
node.end = true;
}
boolean search(String word)
?:首先在前缀树中查找与word最深匹配的节点,最后判断匹配的节点层级是否为词尾,并且此节点为词尾节点。 public boolean search(String word) {
TireNode node = match(word);
// 判断匹配的节点层级是否为词尾,并且此节点为词尾节点。
return node.level == word.length() - 1 && node.end == true;
}
编写函数boolean startsWith(String prefix)
??:首先在前缀树中查找与word最深匹配的节点,判断匹配的节点层级是否输入字符串的末尾 public boolean startsWith(String prefix) {
TireNode node = match(prefix);
// 判断匹配的节点层级是否为输入字符串的末尾
return node.level == prefix.length() - 1;
}