Optimize the code · Easy
Speed Up the Most Frequent Word
Easy Make it fast Seen at Amazon, Bloomberg
mostFrequentWord(words) returns the word that appears most often. If several words share the highest count, return the alphabetically smallest of them.
The version below recounts the whole list for every word. It is correct, but a 50,000-word log takes far too long. Make it fast without changing the results.
Example 1
Input: words = ["b", "a", "b", "a", "c"] Output: "a" Explanation: a and b both appear twice; a is alphabetically first.
Constraints
1 <= words.length <= 100000
The slow code
Every case must finish within 300 ms (budgets are per language in the editor).
function mostFrequentWord(words) {
let best = null;
let bestCount = 0;
for (const w of words) {
let count = 0;
for (const x of words) if (x === w) count++;
if (count > bestCount || (count === bestCount && w < best)) {
best = w;
bestCount = count;
}
}
return best;
}
function mostFrequentWord(words: string[]): string {
let best = "";
let bestCount = 0;
for (const w of words) {
let count = 0;
for (const x of words) if (x === w) count++;
if (count > bestCount || (count === bestCount && w < best)) {
best = w;
bestCount = count;
}
}
return best;
}
def most_frequent_word(words: list[str]) -> str:
best, best_count = "", 0
for w in words:
count = 0
for x in words:
if x == w:
count += 1
if count > best_count or (count == best_count and w < best):
best, best_count = w, count
return best
<?php
function mostFrequentWord(array $words): string
{
$best = '';
$bestCount = 0;
foreach ($words as $w) {
$count = 0;
foreach ($words as $x) {
if ($x === $w) {
$count++;
}
}
if ($count > $bestCount || ($count === $bestCount && strcmp($w, $best) < 0)) {
$best = $w;
$bestCount = $count;
}
}
return $best;
}
class Solution {
public String mostFrequentWord(String[] words) {
String best = "";
int bestCount = 0;
for (String w : words) {
int count = 0;
for (String x : words) if (x.equals(w)) count++;
if (count > bestCount || (count == bestCount && w.compareTo(best) < 0)) {
best = w;
bestCount = count;
}
}
return best;
}
}
Hints
Hint 1
How many times is each word counted?
Hint 2
One pass with a hash map from word to count, then one pass over the map.
Make it faster
Loading the editor… (JavaScript is required to run code in your browser.)
Solution and explanation
Show the solution
Time O(n) · Space O(d) for d distinct words
Why it is slow: for each of the n words the inner loop scans all n words, so the work is n^2: 2.5 billion comparisons for 50,000 words, although there are only a few hundred distinct words.
The fix: count every word once into a hash map (O(n)), then pick the best entry from the map (O(distinct words)), breaking ties alphabetically.
Optimized solution
function mostFrequentWord(words) {
const counts = new Map();
for (const w of words) counts.set(w, (counts.get(w) ?? 0) + 1);
let best = null;
let bestCount = 0;
for (const [w, c] of counts) {
if (c > bestCount || (c === bestCount && w < best)) {
best = w;
bestCount = c;
}
}
return best;
}
function mostFrequentWord(words: string[]): string {
const counts = new Map<string, number>();
for (const w of words) counts.set(w, (counts.get(w) ?? 0) + 1);
let best = "";
let bestCount = 0;
for (const [w, c] of counts) {
if (c > bestCount || (c === bestCount && w < best)) {
best = w;
bestCount = c;
}
}
return best;
}
from collections import Counter
def most_frequent_word(words: list[str]) -> str:
counts = Counter(words)
return min(counts, key=lambda w: (-counts[w], w))
<?php
function mostFrequentWord(array $words): string
{
$counts = [];
foreach ($words as $w) {
$counts[$w] = ($counts[$w] ?? 0) + 1;
}
$best = '';
$bestCount = 0;
foreach ($counts as $w => $c) {
$w = (string) $w; // numeric-looking keys become ints in PHP arrays
if ($c > $bestCount || ($c === $bestCount && strcmp($w, $best) < 0)) {
$best = $w;
$bestCount = $c;
}
}
return $best;
}
class Solution {
public String mostFrequentWord(String[] words) {
Map<String, Integer> counts = new HashMap<>();
for (String w : words) counts.merge(w, 1, Integer::sum);
String best = "";
int bestCount = 0;
for (Map.Entry<String, Integer> e : counts.entrySet()) {
int c = e.getValue();
if (c > bestCount || (c == bestCount && e.getKey().compareTo(best) < 0)) {
best = e.getKey();
bestCount = c;
}
}
return best;
}
}
Common mistakes
- Sorting the entries just to take the first one: fine for correctness, O(d log d) instead of O(d).
- Forgetting the alphabetical tie-break.
Follow-up questions
- Return the top k words (heap of size k, or bucket sort by count).
- The words arrive as an endless stream: approximate counts with a count-min sketch.
More Code Clinic: Make It Fast problems
- Speed Up Contains Duplicate · Easy
- Speed Up Two Sum · Easy
- Speed Up Recursive Fibonacci · Easy
- Speed Up the Active-Customer Join · Easy
- Speed Up Range Sum Queries · Medium
- Speed Up Longest Consecutive Sequence · Medium