#648 Replace Words
frequently reported atByteDance / TikTokMicrosoftGoogle
the problem
In plain words
Given a dictionary of roots and a sentence, replace every word in the sentence by the shortest root that is a prefix of it. Words with no root stay unchanged.
in dictionary = ["cat","bat","rat"], sentence = "the cattle was rattled by the battery"
out "the cat was rat by the bat"
in dictionary = ["a","b","c"], sentence = "aadsfasf absbs bbab cadsfafs"
out "a a b c"
- 1 ≤ dictionary.length ≤ 1000
- 1 ≤ dictionary[i].length ≤ 100
- 1 ≤ sentence.length ≤ 10⁶
- Words separated by single spaces
your turn
Try it before you peek
Read the examples, say the brute force out loud, then write code: here or on LeetCode ↗. Stuck for 20 minutes? Open one hint at a time.
Solve it in the browser
LeetCode-style: complete the class. Compiled by the real javac (Java 17) and judged right here — nothing is sent anywhere.
Solutions are hidden so you can try first. Even 20 minutes of real effort makes the answer stick far better than reading it.
Marking the problem solved, or opening every hint, also shows it.
the aha
Key insight
patternTrie (prefix tree)
Walk each word down a trie of roots. The first end-of-word node you hit is the shortest root — no need to try every prefix length.
solutions
From brute force to optimal
For each word, check prefixes of length 1, 2, 3, … against a set of roots; the first hit is the shortest.
- roots = new HashSet<>(dictionary).
- For each word, for len = 1..L: if roots contains word[0..len) → replace and stop.
Each prefix check builds a substring and hashes it: O(len) each, up to L checks per word (D = letters in the dictionary).
The set of roots and the split sentence.
class Solution { public String replaceWords(List<String> dictionary, String sentence) { Set<String> roots = new HashSet<>(dictionary); String[] words = sentence.split(" "); for (int w = 0; w < words.length; w++) { for (int len = 1; len <= words[w].length(); len++) { // shortest prefix first String prefix = words[w].substring(0, len); // O(len) copy + hash if (roots.contains(prefix)) { words[w] = prefix; break; } } } return String.join(" ", words); }}Insert all roots in a trie. For each word, walk letter by letter and stop at the first node with isEnd.
- Build the trie of roots.
- For each word: walk; if a child is missing → keep the word; if isEnd → output the prefix so far.
- Join with spaces.
Each dictionary letter is inserted once, and each sentence letter is visited at most once (n = sentence length).
Trie nodes plus the output string.
class Solution { private static class Node { Node[] children = new Node[26]; boolean isEnd; } public String replaceWords(List<String> dictionary, String sentence) { Node root = new Node(); for (String r : dictionary) { Node cur = root; for (char ch : r.toCharArray()) { int i = ch - 'a'; if (cur.children[i] == null) cur.children[i] = new Node(); cur = cur.children[i]; } cur.isEnd = true; } StringBuilder out = new StringBuilder(); for (String word : sentence.split(" ")) { if (out.length() > 0) out.append(' '); out.append(shortestRoot(root, word)); } return out.toString(); } /** Walk the word; the first end-of-word node we meet is the shortest root. */ private String shortestRoot(Node root, String word) { Node cur = root; for (int i = 0; i < word.length(); i++) { cur = cur.children[word.charAt(i) - 'a']; if (cur == null) return word; // no root fits: keep the word if (cur.isEnd) return word.substring(0, i + 1); } return word; }}in the room
How to say it in the interview
talk track
- Point out that the trie gives the shortest root for free: we stop at the first end flag, which is the shortest by construction.
traps
- Stopping at the longest root instead of the shortest.
- Building the result with
+=in a loop — O(n²) copying; use a StringBuilder or String.join.
what they ask next
Follow-ups
Replace each word by the longest root instead?
Keep walking past end nodes and remember the last one you saw. Stop at a missing child or the end of the word, then use that last root (or the word if there was none). Still O(D + n).
New roots are added between sentences?
Insert each new root into the same trie in O(its length). Nothing needs rebuilding.
before you submit
Edge cases to test
- Nested roots ("a", "aa", "aaa") → always the shortest, "a".
- A root longer than the word ("catalogue" vs "cat") → no replacement.
- No root fits any word → the sentence comes back unchanged.
practise next
Similar problems
- #208Implement Trie (Prefix Tree)Mediumin Tries
- #720Longest Word in DictionaryMediumin Tries
- #14Longest Common PrefixEasyin Arrays & Strings