LeetCode Problem: Contains Duplicate
Difficulty: Easy
Topics: Array, Hash Set, Sorting
Series: LeetCode Interview Preparation — From Beginner to Expert
After solving Two Sum and Best Time to Buy and Sell Stock, it's time to learn another fundamental interview pattern:
Use a Hash Set when you need to quickly determine whether you've already seen a value.
This sounds simple, but duplicate detection is one of the most common concepts you'll encounter in coding interviews.
The real lesson isn't just how to solve LeetCode #217.
It's learning to recognize when a set is the right data structure.
You are given an integer array nums.
Return:
trueif any value appears at least twice.
Otherwise, return:
falseInput:
nums = [1, 2, 3, 1]
Output:
trueBecause 1 appears twice.
Input:
nums = [1, 2, 3, 4]
Output:
falseEvery number appears exactly once.
Input:
nums = [1, 1, 1, 3, 3, 4, 3, 2, 4, 2]
Output:
trueThere are several duplicates.
We only need to determine whether at least one exists.
The most straightforward approach is to compare every element with every other element.
For example:
[1, 2, 3, 1]We could check:
1 vs 2
1 vs 3
1 vs 1 → duplicate!def containsDuplicate(nums):
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
if nums[i] == nums[j]:
return True
return FalseThis works.
But it is inefficient.
We potentially compare every pair of elements.
For n elements:
Time Complexity: O(n²)
Space Complexity: O(1)This becomes expensive for large arrays.
We need a better approach.
Instead of repeatedly comparing elements, ask:
"Have I already seen this number?"
For:
[1, 2, 3, 1]we process the numbers one at a time.
Start with:
seen = {}Read:
1Have we seen 1?
NoStore it.
seen = {1}Next:
2Have we seen 2?
NoStore it.
seen = {1, 2}Next:
3Not seen.
seen = {1, 2, 3}Next:
1Have we seen 1?
YES!Therefore:
trueWe don't need to scan the rest of the array.
A set stores unique values.
In Python:
seen = set()We can check whether a value exists using:
if num in seen:and add it using:
seen.add(num)This gives us fast average-case lookup.
def containsDuplicate(nums):
seen = set()
for num in nums:
if num in seen:
return True
seen.add(num)
return FalseThis is the solution you should be able to explain confidently in an interview.
Let's break it down.
seen = set()Initially:
{}Conceptually, it is an empty collection of values we've encountered.
for num in nums:We examine every number.
if num in seen:If the number is already present, we have found a duplicate.
seen.add(num)If it hasn't appeared before, remember it.
If we finish the loop without finding a duplicate:
return FalseConsider:
nums = [4, 7, 2, 7]Initially:
seen = {}Is 4 in seen?
NoAdd it:
seen = {4}Is 7 in seen?
NoAdd it:
seen = {4, 7}Is 2 in seen?
NoAdd it:
seen = {4, 7, 2}Is 7 in seen?
YESReturn:
trueThe algorithm immediately stops.
| Step | Current Number | Seen Before | Duplicate? | Action |
|---|---|---|---|---|
| 1 | 4 | {} | No | Add 4 |
| 2 | 7 | {4} | No | Add 7 |
| 3 | 2 | {4, 7} | No | Add 2 |
| 4 | 7 | {4, 7, 2} | Yes | Return True |
We process each element once.
Each set lookup and insertion is O(1) on average.
Therefore:
O(n)O(n)In the worst case, every number is unique and we store all of them.
You could technically use a list:
seen = []and check:
if num in seen:But membership checking in a list takes:
O(n)in the worst case.
Doing this for every element gives:
O(n²)A hash set provides average:
O(1)membership lookup.
That's why choosing the right data structure matters.
You learned a hash map in Two Sum.
Now we're using a hash set.
What's the difference?
Stores:
key → valueExample:
{
2: 0,
7: 1
}Useful when you need additional information such as:
Stores:
valueExample:
{2, 7, 11}Useful when you only care about:
Does this value exist?
For Contains Duplicate, we don't need the index.
We only need to know whether we've seen the number before.
Therefore:
Set is the cleaner data structure.
There is another common solution.
Sort the array:
[4, 2, 7, 2]becomes:
[2, 2, 4, 7]Now duplicates will appear next to each other.
We can compare adjacent elements.
def containsDuplicate(nums):
nums.sort()
for i in range(1, len(nums)):
if nums[i] == nums[i - 1]:
return True
return FalseIf:
nums[i] == nums[i - 1]then we've found a duplicate.
Sorting typically takes:
O(n log n)Then the scan takes:
O(n)Overall:
O(n log n)Depending on the sorting implementation and constraints, auxiliary space can vary.
The hash-set solution is generally preferable when extra memory is allowed:
O(n)time.
If the interviewer asks:
"Can you solve it in linear time?"
Immediately think:
Hash SetGive:
def containsDuplicate(nums):
seen = set()
for num in nums:
if num in seen:
return True
seen.add(num)
return FalseThen explain:
"I maintain a set of values I've already encountered. Before inserting each number, I check whether it already exists. Set membership is O(1) on average, so the overall solution is O(n)."
That's a strong interview explanation.
Python provides a very concise way to solve this:
def containsDuplicate(nums):
return len(nums) != len(set(nums))Why does it work?
Suppose:
nums = [1, 2, 3, 1]Length of array:
4Set:
{1, 2, 3}Length of set:
3Because:
4 != 3there must be a duplicate.
You can.
But don't make the one-liner your first response.
Interviewers are often evaluating your problem-solving process, not just whether you know Python tricks.
A better approach is:
The interviewer should understand that you know why the solution works.
nums = []There are no duplicates.
falsenums = [10]No duplicate is possible.
falsenums = [1, 2, 3, 4, 5]Answer:
falsenums = [5, 5, 5, 5]Answer:
trueThe second 5 immediately reveals the duplicate.
Consider:
seen.add(num)
if num in seen:
return TrueThis is wrong.
Why?
Because you've already inserted the current number.
It will always be found.
The correct order is:
if num in seen:
return True
seen.add(num)First ask:
"Have I seen it?"
Then:
"If not, remember it."
You could write:
seen = {}and store values.
But if you don't need associated information, a set communicates your intention more clearly:
seen = set()Good code isn't only about correctness.
It should also express the algorithm clearly.
The sorting approach modifies the input:
nums.sort()Sometimes that's perfectly acceptable.
But if the interviewer says:
"Don't modify the input array."
then this approach needs adjustment.
This is why you should always pay attention to constraints.
The real lesson from this problem is:
When a problem asks whether something has appeared before, think about a Set.
Watch for phrases such as:
These are strong signals for a hash set.
The general pattern is:
Array
↓
Create Set
↓
Read current value
↓
Already in Set?
├── YES → Duplicate found
└── NO → Add to Set
↓
ContinueThis pattern appears in many interview problems.
Remember our first problem?
Two Sum used:
Hash Mapbecause we needed:
number → indexContains Duplicate uses:
Hash Setbecause we only need:
number exists?This is an important progression.
You shouldn't just memorize:
"Two Sum = Hash Map"
"Contains Duplicate = Hash Set"Instead ask:
What information do I actually need to remember?
If you need:
value + additional information→ Hash Map.
If you only need:
Does this value exist?→ Hash Set.
Once you've solved Contains Duplicate, the interviewer can easily make the problem harder.
Instead of:
true / falsereturn the duplicate value.
For:
[1, 2, 3, 1, 2]return:
[1, 2]Now you need to think about how to avoid reporting the same duplicate multiple times.
Now a set is no longer enough.
You need:
value → frequencyThis points toward a Hash Map.
Order now matters.
You need to think carefully about when a value first repeats.
Now the interviewer is testing whether you understand the trade-off between:
Timeand:
SpaceDepending on the constraints and values involved, completely different techniques may become possible.
Imagine the interviewer asks:
Interviewer: How would you solve Contains Duplicate?
You might start:
"The brute-force approach is to compare every pair, which is O(n²). We can do better by maintaining a hash set of values we've already seen."
Then:
"For every number, I first check whether it's already in the set. If it is, I return true. Otherwise, I add it to the set."
Then:
"This gives O(n) average time and O(n) space."
That's concise, technically correct, and demonstrates your reasoning.
Don't memorize:
seen = set()Memorize the question that leads to it:
"Do I need to know whether I've seen this value before?"
If the answer is yes:
Think Set.If you need additional information associated with that value:
Think Hash Map.That distinction will save you enormous amounts of time in future LeetCode problems.
Problem:
Determine whether an array contains duplicates.
Brute Force:
Compare every pair.
Time:
O(n²)
Optimized:
Use a Hash Set.
For every number:
If number is already in set:
return True
Add number to set.
If loop finishes:
return False
Time:
O(n) average
Space:
O(n)Before moving to the next problem, try these variations:
Return the first duplicate number.
Return all duplicate numbers.
Count how many duplicate values exist.
Find the value that appears most frequently.
Determine whether two arrays contain any common element.
Find the intersection of two arrays.
These problems will strengthen your understanding of Hash Sets and Hash Maps.
LeetCode #217 looks almost trivial.
But it teaches one of the most useful interview instincts:
Don't repeatedly search through data when you can remember what you've already seen.
The brute-force solution asks:
"Have I seen this value?"
→ Search through previous elements.
→ O(n)for every element.
The optimized solution asks:
"Have I seen this value?"
→ Hash Set lookup.
→ O(1) average.Repeated work becomes constant-time lookup.
That's the power of choosing the right data structure.
And this is exactly the kind of thinking that separates someone who knows syntax from someone who can solve problems efficiently in an interview.
Pixels to Perfection Design that Impresses