🧠
Sorting Roots + Prefix Checking
💡 Sorting roots by length allows early stopping when checking prefixes, improving efficiency over brute force but still not optimal.
Intuition
Sort roots by length ascending. For each word, check roots in order; the first root that is a prefix is the shortest replacement.
Algorithm
- Sort the dictionary roots by length ascending.
- Split the sentence into words.
- For each word, iterate over sorted roots.
- Replace the word with the first root that is a prefix.
- If no root matches, keep the word.
- Join all words back into a sentence.
💡 Sorting helps find shortest prefix quickly but still requires checking many roots for each word.
def replaceWords(dictionary, sentence):
dictionary.sort(key=len)
words = sentence.split()
result = []
for word in words:
replacement = word
for root in dictionary:
if word.startswith(root):
replacement = root
break
result.append(replacement)
return ' '.join(result)
# Driver code
if __name__ == '__main__':
dict_roots = ["cat", "bat", "rat"]
sentence = "the cattle was rattled by the battery"
print(replaceWords(dict_roots, sentence))
Line Notes
dictionary.sort(key=len)Sort roots by length to find shortest prefix first
words = sentence.split()Split sentence into words
for word in words:Process each word
for root in dictionary:Check roots in ascending length order
if word.startswith(root):If root is prefix, replace immediately
breakStop checking further roots once shortest prefix found
result.append(replacement)Add replaced word to result
return ' '.join(result)Reconstruct sentence
import java.util.*;
public class ReplaceWords {
public static String replaceWords(List<String> dictionary, String sentence) {
dictionary.sort(Comparator.comparingInt(String::length));
String[] words = sentence.split(" ");
StringBuilder sb = new StringBuilder();
for (String word : words) {
String replacement = word;
for (String root : dictionary) {
if (word.startsWith(root)) {
replacement = root;
break;
}
}
sb.append(replacement).append(" ");
}
return sb.toString().trim();
}
public static void main(String[] args) {
List<String> dict = Arrays.asList("cat", "bat", "rat");
String sentence = "the cattle was rattled by the battery";
System.out.println(replaceWords(dict, sentence));
}
}
Line Notes
dictionary.sort(Comparator.comparingInt(String::length));Sort roots by length ascending
String[] words = sentence.split(" ");Split sentence into words
for (String word : words)Iterate over each word
for (String root : dictionary)Check roots in order
if (word.startsWith(root))If root is prefix, replace word
break;Stop checking once shortest prefix found
sb.append(replacement).append(" ");Append replaced word
return sb.toString().trim();Return final sentence
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
string replaceWords(vector<string>& dictionary, string sentence) {
sort(dictionary.begin(), dictionary.end(), [](const string& a, const string& b) {
return a.size() < b.size();
});
vector<string> words;
string word, result;
for (int i = 0, n = sentence.size(); i <= n; ++i) {
if (i == n || sentence[i] == ' ') {
words.push_back(word);
word = "";
} else {
word += sentence[i];
}
}
for (auto& w : words) {
string replacement = w;
for (auto& root : dictionary) {
if (w.compare(0, root.size(), root) == 0) {
replacement = root;
break;
}
}
result += replacement + " ";
}
if (!result.empty()) result.pop_back();
return result;
}
int main() {
vector<string> dict = {"cat", "bat", "rat"};
string sentence = "the cattle was rattled by the battery";
cout << replaceWords(dict, sentence) << endl;
return 0;
}
Line Notes
sort(dictionary.begin(), dictionary.end(), [](const string& a, const string& b) {Sort roots by length ascending
for (int i = 0, n = sentence.size(); i <= n; ++i)Split sentence into words
words.push_back(word);Add word to list
for (auto& w : words)Iterate over each word
if (w.compare(0, root.size(), root) == 0)Check if root is prefix
replacement = root;Replace word with root
break;Stop checking further roots
result += replacement + " ";Append replaced word
function replaceWords(dictionary, sentence) {
dictionary.sort((a, b) => a.length - b.length);
const words = sentence.split(' ');
const result = [];
for (const word of words) {
let replacement = word;
for (const root of dictionary) {
if (word.startsWith(root)) {
replacement = root;
break;
}
}
result.push(replacement);
}
return result.join(' ');
}
// Test
const dict = ["cat", "bat", "rat"];
const sentence = "the cattle was rattled by the battery";
console.log(replaceWords(dict, sentence));
Line Notes
dictionary.sort((a, b) => a.length - b.length);Sort roots by length ascending
const words = sentence.split(' ');Split sentence into words
for (const word of words)Iterate over each word
for (const root of dictionary)Check roots in order
if (word.startsWith(root))If root is prefix, replace word
replacement = root;Update replacement
break;Stop checking further roots
result.push(replacement);Add replaced word to result
TimeO(m * n * k) but often faster in practice due to early break
SpaceO(m * k) for words and result
Sorting roots helps find shortest prefix early, reducing checks per word but worst case still checks many roots.
💡 Sorting helps but still can be slow if dictionary is large; better data structures exist.
Interview Verdict: Accepted but not optimal for very large inputs
This approach improves over brute force but can still be slow; good stepping stone to trie solution.