Most Common Word — Easy Problem & Solution
Given a paragraph and a list of banned words, return the most frequent word that is not banned.
- Difficulty: Easy
- Topics: Strings, Hash Table
- Asked at: Amazon, Adobe, Infosys
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
Given a paragraph and a list of banned words, return the most frequent word that is not banned.
Words are case-insensitive and the answer is returned in lowercase. Anything that is not a letter separates words. The answer is unique; when several words tie, the one that reaches the winning count first wins.
Example 1
Input: paragraph = "CodeKairo drills, codekairo rounds, codekairo wins!", banned = ["rounds"]
Output: codekairo
Explanation: codekairo appears three times and is not banned.
Example 2
Input: paragraph = "Bob hit a ball, the hit BALL flew far after it was hit.", banned = ["hit"]
Output: ball
Explanation: hit is banned, so ball with two occurrences wins.
Example 3
Input: paragraph = "a, a, a, b", banned = ["a"]
Output: b
Constraints
1 <= paragraph.length <= 10000 <= banned.length <= 100paragraph holds English letters, spaces and the punctuation !?',;.banned words are lowercase and letters only.
How to solve Most Common Word
Tokenise by scanning for maximal runs of letters, lowercase each token, skip the banned ones and count the rest — keeping the running maximum as you go.
Approach
- Put the banned words into a set, lowercased.
- Sweep the paragraph accumulating letters into a buffer; any non-letter flushes the buffer as one word.
- Lowercase the flushed word, skip it if banned, otherwise increment its count.
- Whenever a count strictly exceeds the best so far, adopt that word as the answer.
- Flush once more after the loop so a paragraph ending in a letter is not dropped.
Why it works
Updating the best on a strict > means the first word to reach a given count keeps the title, which is the tie-break the statement describes. Scanning character by character avoids having to enumerate every punctuation mark.
Complexity
- Time —
O(n + b) - Space —
O(n + b)
Pitfalls
- Splitting on spaces alone leaves punctuation stuck to words, so
"ball,"and"ball"count separately. - Forgetting the final flush loses the last word when the paragraph does not end in punctuation.
- Comparing against the banned list case-sensitively misses capitalised occurrences.
Reference solution
Python
from typing import List
def mostCommonWord(paragraph: str, banned: List[str]) -> str:
block = set(b.lower() for b in banned)
count = {}
best, best_n = "", 0
cur = []
def flush():
nonlocal best, best_n, cur
if not cur:
return
w = "".join(cur).lower()
cur = []
if w in block:
return
count[w] = count.get(w, 0) + 1
if count[w] > best_n:
best_n = count[w]
best = w
for c in paragraph:
if c.isalpha():
cur.append(c)
else:
flush()
flush()
return bestJavaScript
var mostCommonWord = function(paragraph, banned) {
var block = {};
for (var b = 0; b < banned.length; b++) block[banned[b].toLowerCase()] = true;
var count = {}, best = "", bestN = 0, cur = "";
var flush = function() {
if (cur.length === 0) return;
var w = cur.toLowerCase();
cur = "";
if (block[w] === true) return;
count[w] = (count[w] === undefined ? 0 : count[w]) + 1;
if (count[w] > bestN) { bestN = count[w]; best = w; }
};
for (var i = 0; i < paragraph.length; i++) {
var c = paragraph.charAt(i);
if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) cur += c;
else flush();
}
flush();
return best;
};Also on the editorial tab: C, C#, C++, Go, Java, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.