String · 29 of 43
Find the first repeated word in string
Read a sentence word by word and report the first word you meet for a second time, using a bag of words you have already seen.
- Simple way
- time O(n^2 * w)
room O(n * w) - Clever way
- time O(n * w)
room O(n * w)
The problem, simply
You get a sentence of words separated by spaces. Read it from left to right. Give back the first word that you meet for the second time. If no word repeats, say so (here we return an empty string).
Below, n is the number of words and w is the length of the longest word.
A story to remember it
Picture it
The words of the sentence in order. had shows up at spot 1 and again at spot 6. been shows up again at spot 7, but had came back first.
- checking
- answer
Examples
A normal sentence
- In
s = 'Ravi had been saying that he had been there'- Out
had
had comes back at spot 6, before been comes back at spot 7.
Two words repeat
- In
s = 'he had had he'- Out
had
Reading left to right, the second had (spot 2) arrives before the second he (spot 3).
No repeats
- In
s = 'Ravi had been saying that'- Out
''
Every word appears once.
Right away
- In
s = 'go go now'- Out
go
The second word is already a repeat.
One word
- In
s = 'hello'- Out
''
A single word cannot repeat.
Way 1: the simple way
For each word, look back at all the words before it. The first word that finds an equal word behind it is the answer.
- Split the sentence into words.
- For
j = 1, 2, ...: comparewords[j]with everywords[i]wherei < j. - The first
jwith a match gives the answer.
class Solution {
public String firstRepeated(String s) {
String[] words = s.trim().split("\\s+");
for (int j = 1; j < words.length; j++) {
for (int i = 0; i < j; i++) {
if (words[i].equals(words[j])) return words[j]; // met it before
}
}
return ""; // no word repeats
}
}How long it takes: about n^2 / 2 pairs of words, and comparing two words takes up to w steps, so O(n^2 * w). Extra room: the array of words, O(n * w).
Way 2: the clever way
Use the basket from the story. In code it is a hash set: you can ask "is this word inside?" in about the time it takes to read the word.
- Split the sentence into words.
- For each word in order: if it is already in the set, return it.
- Otherwise add it to the set.
- If the loop ends, return the empty string.
Read words into the bag until one is already there
01 / 08
Cut the sentence into words. Keep a bag of words we have already read. It starts empty.
- seen
- answer
- just added
- ignored
import java.util.*;
class Solution {
public String firstRepeated(String s) {
Set<String> seen = new HashSet<>();
for (String word : s.trim().split("\\s+")) {
if (!seen.add(word)) return word; // add() says false when the word was already there
}
return "";
}
}How long it takes: each word is hashed and looked up once, O(w) each, so O(n * w), which is the size of the sentence. Extra room: the set may hold every word, O(n * w).
Another way: the other meaning
Some versions of this problem mean something else by "first repeated word": the word that appears earliest in the sentence among all the words that repeat somewhere. For he had had he that is he, because he starts the sentence and also appears later.
For that meaning, count every word first, then walk the words again and return the first one whose count is more than 1.
The other meaning. Count first, then read from the start: he has a count of 2 and comes first, so the answer is he, not had.
- answer
import java.util.*;
class Solution {
public String firstRepeated(String s) {
String[] words = s.trim().split("\\s+");
Map<String, Integer> count = new HashMap<>();
for (String word : words) count.merge(word, 1, Integer::sum); // count everything first
for (String word : words) {
if (count.get(word) > 1) return word; // earliest word that repeats
}
return "";
}
}This also takes O(n * w) time and room, but it must read the whole sentence before answering.
Watch out for
- Splitting on a single space
" "breaks on double spaces and gives empty words. Usetrim()andsplit("\\s+"). - Compare words with
equals, never==. Two equal words fromsplitare different objects. - Case and punctuation:
Hadandhad,are different strings. If they should match, lowercase the sentence and strip punctuation first.
What interviewers ask next
- What if the text is a huge stream you cannot hold in memory? Keep only the set, read word by word, and stop at the first hit. If even the set is too big, a Bloom filter answers "maybe seen" in tiny room, with a second check for the maybes.
- Can a trie replace the set? Yes. Insert each word letter by letter and mark where words end. Reaching an end mark means a repeat. Words that share a start share nodes, which can save room.
- First non repeated word? Count every word, then walk again and return the first word with count 1.
- Most common word, ignoring a list of banned words (LeetCode 819)? Lowercase, strip punctuation, count with a map while skipping banned words, then take the biggest count.
Remember this
Grown-up words: the basket is a hash set, seen.add returning false is a membership test, counting words uses a hash map of frequencies, and w is the cost of hashing a word.