例题:词典中最长的单词
以力扣720题为例:
给出一个字符串数组words组成的一本英语词典。从中找出最长的一个单词,该单词是由words词典中其他单词逐步添加一个字母组成。若其中有多个可行的答案,则返回答案中字典序最小的单词。
若无答案,则返回空字符串。
##示例:
输入:
words = [“w”,“wo”,“wor”,“worl”, “world”]
输出:“world”
**解释: **
单词"world"可由"w", “wo”, “wor”, 和 "worl"添加一个字母组成。
输入:
words = [“a”, “banana”, “app”, “appl”, “ap”, “apply”, “apple”]
输出:“apple”
解释:
“apply"和"apple"都能由词典中的单词组成。但是"apple"的字典序小于"apply”。
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');
}
// 前缀树插入
// 举例:插入"ap"、"app"、"apc"、
// 前缀树树结构如下:
// '0'
// |
// 'a'
// |
// 'p'
// |————
// | |
// 'p' 'c'
public void insert(String word, int index) {
Node cur = root;
// 套路: 后续字符加到上一字符的map中
for (char c: word.toCharArray()) {
cur.children.putIfAbsent(c, new Node(c));
cur = cur.children.get(c);
}
// 在最后字符节点保存索引,以对应string数组内的单词索引
cur.end = index;
}
public String dfs() {
String ans = "";
Stack<Node> stack = new Stack();
stack.push(root);
while (!stack.empty()) {
Node node = stack.pop();
// 仅前缀树最深处字符节点有保存索引,其他节点的end值为int默认值0
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;
}
}
评论区