Uncommon Words from Two Sentences: Hash Map Counting
Uncommon Words from Two Sentences (LeetCode 884) asks you to find every word that appears exactly once across two sentences combined. You are given two strings s1 and s2, each consisting of lowercase words separated by spaces. A word is "uncommon" if it appears exactly one time total across both sentences. Return a list of all uncommon words in any order.
For example, s1 = "this apple is sweet" and s2 = "this apple is sour". The words "this", "apple", and "is" each appear twice (once in each sentence), so they are not uncommon. "sweet" and "sour" each appear once total. The answer is ["sweet", "sour"].
Why this problem matters
At first glance, you might think you need to compare the two sentences against each other, looking for words that exist in one but not the other. That instinct leads to a more complicated approach than necessary. The key realization is simpler: just count every word across both sentences in one combined frequency map, then grab anything with a count of exactly one.
This insight, that combining two inputs before processing is easier than comparing them separately, shows up in many problems. It turns a "compare two things" problem into a "count and filter" problem, which is almost always cleaner.
The frequency counting pattern here is the same one you will use in Group Anagrams, Valid Anagram, and Most Common Word. Practicing it on an easy problem like this builds the muscle memory you need for those harder variations.
The counting approach
The plan is three steps:
- Combine and split. Concatenate the two sentences (with a space between them) and split the result into individual words.
- Count everything. Build a frequency map where each key is a word and each value is how many times it appears across both sentences.
- Filter. Return every word whose count is exactly 1.
That is it. No need to track which word came from which sentence. No need for set intersection or difference. Just count and filter.
Step 1: Split both sentences into individual words.
Split s1 = "this apple is sweet" and s2 = "this apple is sour" on spaces. We get 4 words from each sentence.
Step 2: Count each word across both sentences combined.
Merge all words into one frequency map. "this", "apple", and "is" each appear in both sentences, so their counts are 2.
Step 3: Collect all words with count == 1.
Only "sweet" and "sour" have a count of exactly 1. These are the uncommon words. Return them as the answer.
Clean solution
from collections import Counter
def uncommon_from_sentences(s1: str, s2: str) -> list[str]:
count = Counter((s1 + " " + s2).split())
return [word for word in count if count[word] == 1]
Complexity analysis
| Approach | Time | Space |
|---|---|---|
| Hash map counting | O(n + m) | O(n + m) |
Here n and m are the lengths of s1 and s2. Splitting is linear, counting is linear (each word is inserted into the hash map in O(1) amortized time), and the final filter pass is linear in the number of distinct words.
Edge cases to watch for
- A word appears twice in the same sentence. For example,
s1 = "apple apple"ands2 = "banana". The word "apple" has count 2, so it is not uncommon, even though it only appears in one sentence. The definition is about total count across both sentences, not which sentence it came from. - One sentence is empty. The problem guarantees at least one word per sentence, but if you are coding defensively, splitting an empty string in Python gives
[], so the logic still works. - All words are shared. If both sentences contain exactly the same words, every word has count 2 or more. The result is an empty list.
- No overlap at all. If the two sentences share no words, every word has count 1, and they are all uncommon.
- Single-word sentences.
s1 = "hello"ands2 = "hello"returns[]. Buts1 = "hello"ands2 = "world"returns["hello", "world"].
The building blocks
This problem is made of two patterns you will reuse constantly.
Frequency counting with Counter. The act of splitting a string into tokens and tallying occurrences. The template is:
count = Counter(text.split())
You see this same structure in Most Common Word (with additional filtering), Valid Anagram (comparing two frequency maps), and dozens of other string problems. Once you internalize this one-liner, the "counting" step of any word-frequency problem takes zero thought.
Filtering by count value. After building the frequency map, you scan it for entries that meet some condition. Here the condition is count == 1, but the shape is the same whether you are looking for the max count, elements above a threshold, or characters that appear an odd number of times.
[key for key in count if count[key] == 1]
These two pieces snap together here in the simplest way possible. In harder problems, the counting step might involve normalization (lowercasing, sorting characters), and the filtering step might involve more complex conditions. But the skeleton is always the same.
From understanding to recall
Uncommon Words from Two Sentences is a two-line solution once you see the pattern. But "seeing the pattern" in the heat of an interview is a different skill from understanding an explanation after the fact. You need the Counter plus filter template to come to mind automatically the moment a problem mentions word frequencies.
Spaced repetition bridges that gap. You practice the counting pattern from scratch at increasing intervals until the code lives in your fingers. When you encounter a harder problem that uses the same building block, like grouping anagrams or finding the most common word, you will not waste time re-deriving the frequency map. You will already know it and can focus on the new twist.
Related posts
- Group Anagrams - Another hash map problem grouping strings
- Valid Anagram - Frequency counting for character-level comparison
- Most Common Word - Similar word frequency counting pattern