Skip to main content

Longest Word in Dictionary


Longest Word in Dictionary: Given an array of strings words representing an English Dictionary, return the longest word in words that can be built one character at a time by other words in words.

If there is more than one possible answer, return the longest word with the smallest lexicographical order. If there is no answer, return the empty string.

Note that the word should be built from left to right with each additional character being added to the end of a previous word.

Example 1:
Input: words = ["w","wo","wor","worl","world"]
Output: "world"
Explanation: The word "world" can be built one character at a time
by "w", "wo", "wor", and "worl".

Example 2:
Input: words = ["a","banana","app","appl","ap","apply","apple"]
Output: "apple"
Explanation: Both "apply" and "apple" can be built from other words in the dictionary.
However, "apple" is lexicographically smaller than "apply".

Constraints:
  • 1 <= words.length <= 1000
  • 1 <= words[i].length <= 30
  • words[i] consists of lowercase English letter.

Try this Problem on your own or check similar problems:

  1. Longest Word in Dictionary through Deleting
  2. Implement Magic Dictionary
Solution:
class Solution {
class Trie {
private class TrieNode{
TrieNode[] children;
boolean isWord = false;
String word;
public TrieNode(){
children = new TrieNode[26];
}
}

TrieNode root;
public Trie() {
root = new TrieNode();
}

public void insert(String word) {
TrieNode iter = root;
for(int i = 0; i < word.length(); ++i){
char letter = word.charAt(i);
if(iter.children[letter - 'a'] == null){
iter.children[letter - 'a'] = new TrieNode();
}
iter = iter.children[letter - 'a'];
}
iter.isWord = true;
iter.word = word;
}


public String longestWord() {
String result = "";
Queue<TrieNode> q = new LinkedList<>();
q.offer(root);
while (!q.isEmpty()) {
int size = q.size();
while(size-->0){
TrieNode node = q.poll();
for (int j = 25; j >= 0; j--) {
if (node.children[j] != null && node.children[j].isWord) {
result = node.children[j].word;
q.add(node.children[j]);
}
}
}
}
return result;
}
}

public String longestWord(String[] words) {
Trie trie = new Trie();
for(String word: words){
trie.insert(word);
}
return trie.longestWord();
}
}

Time/Space Complexity:
  • Time Complexity: O(sum(w))
  • Space Complexity: O(sum(w))

Explanation:

We could use a set and put all the words from the input array to it, and for each word check if all of it's prefixes are present in the set, but since we're working with prefixes natural choice would be to build a trie, insert every word into trie and then do a modified BFS approach to find the longest word. We utilize the implementation we did in Implement Trie (Prefix Tree) without the search function and for insert we have only a minor modification since we're holding the exact word for each node that represents the end of that word. Since we do bfs in reverse order on the children we can be sure that the result would contain the longest word (deepest level) but also the one with smallest lexicographical order (since the last node which is checked is the node with smallest letter in lexicographical sense, for example 'a'). To search and build the trie we will spend time and space complexity corresponding to the sum of lengths of all words.