Trie,又称前缀树或字典树,是一棵有根树.
实现 Trie (前缀树)(力扣 208)
插入字符串
插入字符串,对于当前字符对应的子节点,有两种情况:
子节点存在:沿着指针移动到子节点,继续处理下一个字符。
子节点不存在:创建一个新的子节点,记录在 children 数组的对应位置上,然后继续搜索下一个字符。
查找前缀
查找前缀,有两种情况:
子节点存在:沿着指针移动到子节点,继续搜索下一个字符。
子节点不存在:说明字典树中不包含该前缀,返回空指针。
class Trie {
private Trie[] children;
private boolean isEnd;
public Trie() {
children = new Trie[26];
isEnd = false;
}
public void insert(String word) {
Trie node = this;
for (int i = 0; i < word.length(); i++) {
char ch = word.charAt(i);
int index = ch - 'a';
if (node.children[index] == null) {
node.children[index] = new Trie();
}
node = node.children[index];
}
node.isEnd = true;
}
public boolean search(String word) {
Trie node = searchPrefix(word);
return node != null && node.isEnd;
}
public boolean startsWith(String prefix) {
return searchPrefix(prefix) != null;
}
private Trie searchPrefix(String prefix) {
Trie node = this;
for (int i = 0; i < prefix.length(); i++) {
char ch = prefix.charAt(i);
int index = ch - 'a';
if (node.children[index] == null) {
return null;
}
node = node.children[index];
}
return node;
}
}
词典中最长的单词(力扣 720)
class Solution {
public String longestWord(String[] words) {
Trie trie = new Trie();
int index = 0;
for (String word: words) {
trie.insert(word, ++index); //indexed by 1
}
trie.words = words;
return trie.dfs();
}
}
class Node {
char c;
HashMap<Character, Node> children = new HashMap();
int end;
public Node(char c){
this.c = c;
}
}
class Trie {
Node root;
String[] words;
public Trie() {
root = new Node('0');
}
public void insert(String word, int index) {
Node cur = root;
for (char c: word.toCharArray()) {
cur.children.putIfAbsent(c, new Node(c));
cur = cur.children.get(c);
}
cur.end = index;
}
public String dfs() {
String ans = "";
Stack<Node> stack = new Stack();
stack.push(root);
while (!stack.empty()) {
Node node = stack.pop();
if (node.end > 0 || node == root) {
if (node != root) {
String word = words[node.end - 1];
if (word.length() > ans.length() ||
word.length() == ans.length() && word.compareTo(ans) < 0) {
ans = word;
}
}
for (Node nei: node.children.values()) {
stack.push(nei);
}
}
}
return ans;
}
}
前K个高频单词(力扣 692)
class Solution {
class TrieNode {
private TrieNode[] children;
private boolean isEnd;
private final int R = 26;
private int appearTimes;
private boolean hasChildren;
private String word;
public TrieNode() {
isEnd = false;
children = new TrieNode[R];
appearTimes = 0;
hasChildren = false;
}
public boolean containsChar(char ch) {
return children[ch-'a'] != null;
}
public boolean isEnd() {
return isEnd;
}
public void setEnd(boolean _isEnd) {
isEnd = _isEnd;
appearTimes++;
}
public TrieNode get(char ch) {
return children[ch-'a'];
}
public void put(char ch, TrieNode node) {
children[ch-'a'] = node;
hasChildren = true;
}
public TrieNode[] getChildren() {
return children;
}
public int getAppearTimes() {
return appearTimes;
}
public boolean hasChildren() {
return hasChildren;
}
public String getCurrentWord() {
return word;
}
public void setCurrentWord(String _word) {
word = _word;
}
}
class Trie {
private TrieNode root;
public Trie() {
root = new TrieNode();
}
public TrieNode getRoot() {
return root;
}
public void insert(String word) {
TrieNode node = root;
for( int i = 0; i < word.length(); i++ ) {
char currentChar = word.charAt(i);
if( !node.containsChar(currentChar) ) {
node.put(currentChar, new TrieNode());
}
node = node.get(currentChar);
}
node.setEnd(true);
node.setCurrentWord(word);
}
public boolean search(String word) {
TrieNode node = root;
for( int i = 0; i < word.length(); i++ ) {
char currentChar = word.charAt(i);
if( node.containsChar(currentChar) ) {
node = node.get(currentChar);
}
else {
return false;
}
}
return node.isEnd();
}
public boolean searchPrefix(String prefix) {
TrieNode node = root;
for( int i = 0; i < prefix.length(); i++ ) {
char currentChar = prefix.charAt(i);
if( node.containsChar(currentChar) ) {
node = node.get(currentChar);
}
else {
return false;
}
}
return true;
}
}
public List<String> topKFrequent(String[] words, int k) {
Trie trie = new Trie();
for( String str : words ) {
trie.insert(str);
}
HashMap<String, Integer> count = new HashMap<String, Integer>();
dfs(trie.getRoot(), count);
class WordComparator implements Comparator<String> {
public int compare(String s1, String s2) {
int times1 = count.get(s1);
int times2 = count.get(s2);
if( times1 < times2 ) {
return -1;
}
else if( times1 > times2 ) {
return 1;
}
else {
return s2.compareTo(s1);
}
}
}
PriorityQueue<String> heap = new PriorityQueue<String>(new WordComparator());
for (String word: count.keySet()) {
heap.offer(word);
if (heap.size() > k) {
heap.poll();
}
}
List<String> ans = new ArrayList();
while (!heap.isEmpty()) {
ans.add(heap.poll());
}
Collections.reverse(ans);
return ans;
}
private void dfs(TrieNode node, HashMap<String, Integer> count) {
if( node.isEnd() ) {
count.put(node.getCurrentWord(), node.getAppearTimes());
}
if( !node.hasChildren() ) {
return ;
}
TrieNode[] children = node.getChildren();
for( int i = 0; i < children.length; i++ ) {
if( children[i] != null ) {
dfs(node.children[i], count);
}
}
}
}