https://leetcode.com/problems/longest-word-in-dictionary/
In this problem, we build a Trie, and then we traverse it and try to get the leaf with the longest word. A simple twist is that, at every node, we only traverse further to a child if and only if the child is a word node, meaning it corresponds to a word existed in the dictionary.
In Java:
static class Solution {
public String longestWord(String[] words) {
//Build Trie
Trie trie = new Trie();
trie.buildTrie(words);
return trie.getLongestWord();
}
public class Trie {
private TrieNode root;
protected class TrieNode {
HashMap<Character, TrieNode> next;
String word;
protected TrieNode() {
next = new HashMap<>();
}
}
public TrieNode buildTrie(String[] words) {
root = new TrieNode();
for (String w : words) {
TrieNode p = root;
for (char c : w.toCharArray()) {
if (!p.next.containsKey(c)) p.next.put(c, new TrieNode());
p = p.next.get(c);
}
p.word = w;
}
return root;
}
HashMap<TrieNode, String> memoryMap = new HashMap<>();
public String dfs(TrieNode node) {
if (memoryMap.containsKey(node)) {
return memoryMap.get(node);
}
if (node == null) {
return "";
}
if (node.next.size() == 0) {
//This is a leaf node
return node.word;
}
String result = node.word!=null?node.word:"";
for (TrieNode t : node.next.values()) {
if (t.word != null) {
//valid child
String s = dfs(t);
result = result.length() > s.length()?
result: result.length()<s.length()?
s: result.compareTo(s) < 0 ? result : s;
}
}
memoryMap.put(node, result);
return result;
}
public String getLongestWord() {
return dfs(root);
}
}
}
In Kotlin
class Solution {
fun longestWord(words: Array<String>): String? {
//Build Trie
val trie = Trie()
trie.buildTrie(words)
return trie.longestWord
}
inner class Trie {
private var root = TrieNode()
var memoryMap = HashMap<TrieNode, String>()
val longestWord: String?
get() = dfs(root)
inner class TrieNode() {
var next: HashMap<Char, TrieNode> = HashMap()
var word: String? = null
}
fun buildTrie(words: Array<String>): TrieNode {
for (w in words) {
var p: TrieNode = root
for (c in w.toCharArray()) {
p.next.computeIfAbsent(c) {TrieNode()}
p = p.next[c]!!
}
p.word = w
}
return root
}
fun dfs(node: TrieNode?): String {
if (memoryMap.containsKey(node)) {
return memoryMap[node]!!
}
if (node == null) {
return ""
}
if (node.next.size == 0) {
//This is a leaf node
return node.word?:""
}
var result = node.word?:""
for (t in node.next.values) {
if (t.word != null) {
//valid child
val s = dfs(t)
result = if (result.length > s.length)
result
else if (result.length < s.length)
s
else if (result < s) result else s
}
}
memoryMap[node] = result
return result
}
}
}
}