Contains Duplicate
Detect any duplicate in an array — Set vs sort, O(n) hash, and follow-ups like nearby duplicates (k-window).
- dsa
- arrays
- interview
- Meta
The problem
Return true if any value appears at least twice in nums, else false.
[1, 2, 3, 1] → true
[1, 2, 3, 4] → false
Warm-up for hash sets. Same pattern as “has this id already been seen in this session?”
Brute force
function containsDuplicateBrute(nums: number[]): boolean {
for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length; j++) {
if (nums[i] === nums[j]) return true;
}
}
return false;
}
| Time | O(n²) |
| Space | O(1) |
Sort approach
function containsDuplicateSort(nums: number[]): boolean {
const a = [...nums].sort((x, y) => x - y);
for (let i = 1; i < a.length; i++) {
if (a[i] === a[i - 1]) return true;
}
return false;
}
| Time | O(n log n) |
| Space | O(n) copy or O(1) if mutating allowed |
Optimal: Set
function containsDuplicate(nums: number[]): boolean {
const seen = new Set<number>();
for (const x of nums) {
if (seen.has(x)) return true;
seen.add(x);
}
return false;
}
// or one-liner (no early exit on large unique prefix + dupe at end same asymp)
function containsDuplicateOneLiner(nums: number[]): boolean {
return new Set(nums).size !== nums.length;
}
| Time | O(n) average |
| Space | O(n) |
Early-exit version is better when a duplicate appears early.
Edge cases
- Empty / single element → false
- All same → true
- Negatives and zeros
- Very large n — space tradeoff vs sort
Follow-ups
- Contains Duplicate II — duplicate within distance
k→ sliding window Set - III — nearby in value and index → buckets / tree map
function containsNearbyDuplicate(nums: number[], k: number): boolean {
const window = new Set<number>();
for (let i = 0; i < nums.length; i++) {
if (window.has(nums[i])) return true;
window.add(nums[i]);
if (window.size > k) window.delete(nums[i - k]);
}
return false;
}
Interview delivery
- Restate.
- Brute → sort → set.
- Prefer early-exit Set.
- O(n)/O(n).
- Mention nearby-duplicate follow-up.
Mental model
Membership query: “have I seen this value?” Hash set is the default tool. Sorting is the comparison-model alternative when hash tables are disallowed or memory is tighter for some reason.
Production cousin: detecting duplicate request ids, double-submit tokens, or React keys collisions in a list.
Complexity tradeoffs to say
| Approach | Time | Space | Mutates input? |
|---|---|---|---|
| Nested loops | O(n²) | O(1) | no |
| Sort in place | O(n log n) | O(1) | yes |
| Sort copy | O(n log n) | O(n) | no |
| Set early exit | O(n) avg | O(n) | no |
| Set size compare | O(n) | O(n) | no |
Out-loud answer
“Return true if any value repeats. I’ll scan into a Set and return on first collision — O(n) time O(n) space. Sort is O(n log n) if hashing is off the table. Follow-up: duplicates within distance k uses a sliding window set.”