LeetCode ยท #217

Contains Duplicate Solution

Given an integer array nums, return true if any value appears at least twice, and false if every element is distinct.

01
Section One ยท Problem

Problem Statement

๐Ÿท๏ธ

Difficulty

Easy

๐Ÿ”—

LeetCode

Problem #217

๐Ÿ—๏ธ

Pattern

Hash Set โ€” duplicate detection

Given an integer array nums, return true if any value appears at least twice in the array, and return false if every element is distinct.

Example 1
Input: nums = [1, 2, 3, 1] Output: true // Because nums[0] == nums[3] == 1 โ€” duplicate found
Example 2
Input: nums = [1, 2, 3, 4] Output: false // All elements are distinct
Constraints
โ€ข 1 โ‰ค nums.length โ‰ค 10โต โ€ข -10โน โ‰ค nums[i] โ‰ค 10โน โ†‘ Large range โ€” sorting works, but HashSet gives O(1) per lookup
02
Section Two ยท Approach 1

Brute Force โ€” O(nยฒ)

Compare every element against every other element. Two nested loops โ€” the outer picks one number, the inner checks all subsequent numbers for a match. If any pair is equal, return true.

Why it works

By exhaustively checking every pair (i, j) where j > i, we're guaranteed to find a duplicate if one exists. No element is missed because we cover all possible pairs.

Why we can do better
Problem: For each element, we re-scan the array asking "does this value exist again?" โ€” but a HashSet answers that question in O(1). The inner loop does O(n) work per element that a set lookup eliminates entirely.
Java โ€” Brute Force
class Solution { public boolean containsDuplicate(int[] nums) { for (int i = 0; i < nums.length; i++) { for (int j = i + 1; j < nums.length; j++) { if (nums[i] == nums[j]) { return true; } } } return false; // no duplicates found } }
Python โ€” Brute Force
class Solution: def containsDuplicate(self, nums: list[int]) -> bool: for i in range(len(nums)): for j in range(i + 1, len(nums)): if nums[i] == nums[j]: return True return False # no duplicates
MetricValue
TimeO(nยฒ) โ€” every pair checked
SpaceO(1) โ€” no extra storage
03
Section Three ยท Approach 2

HashSet โ€” O(n)

The question boils down to: "have I seen this number before?" โ€” a membership test. A HashSet tracks every value we've encountered and answers that question in O(1) per lookup.

๐Ÿ’ก Mental model: Imagine a bouncer at a concert checking wristbands. Each attendee gets a unique wristband color on entry. When someone walks in, the bouncer glances at the rack of used colors โ€” if that color is already taken, the person is a duplicate. The bouncer doesn't scan the crowd; the rack (your HashSet) gives an instant answer.
Algorithm โ€” One-pass HashSet
  • Step 1: Create an empty HashSet<Integer>.
  • Step 2: For each element nums[i], check if it already exists in the set.
  • Step 3: If set.contains(nums[i]) โ†’ return true (duplicate found).
  • Step 4: Otherwise, add nums[i] to the set and continue.
  • Step 5: If we exhaust the array without a match โ†’ return false.
๐ŸŽฏ When to recognize this pattern:
  • Any time a problem asks "does a value repeat?", "are all elements unique?", or "find the first duplicate" โ€” think HashSet duplicate detection.
  • The signal is a membership question over a growing collection.
  • This same pattern appears in LC 217, LC 219 (Contains Duplicate II with index constraint), LC 128 (Longest Consecutive Sequence), and LC 349 (Intersection of Two Arrays).
Why one pass is enough:
  • We check before inserting.
  • If element X appears at indices 3 and 7, when we reach index 7 the set already holds X from index 3 โ€” immediate detection.
  • We never need to look backward or make a second pass. The set accumulates history as we go.
04
Section Four ยท Trace

Visual Walkthrough

Trace through nums = [1, 2, 3, 1]:

One-pass HashSet โ€” all 4 iterations
ARRAY 1 i=0 2 i=1 3 i=2 1 i=3 Step 1 โ€” i=0, nums[i]=1 set contains 1? No โ†’ add 1 to set set: { 1 } Step 2 โ€” i=1, nums[i]=2 set contains 2? No โ†’ add 2 to set set: { 1, 2 } Step 3 โ€” i=2, nums[i]=3 set contains 3? No โ†’ add 3 to set set: { 1, 2, 3 } Step 4 โ€” i=3, nums[i]=1 set contains 1? โœ“ YES โ€” duplicate found! โ†’ return true โœ“ โ€” DONE, exit early FOUND! 1 already in set Answer: true โ€” duplicate 1 at i=0 and i=3
Notice:
  • We found the duplicate on the fourth element โ€” meaning we processed 3 elements before detecting it.
  • In the worst case (no duplicates), we'd scan the entire array building up the set โ€” still O(n).
  • In the best case (duplicate at position 1), we exit after two elements.
05
Section Five ยท Implementation

Code โ€” Java & Python

Java โ€” One-pass HashSet
import java.util.HashSet; class Solution { public boolean containsDuplicate(int[] nums) { HashSet<Integer> seen = new HashSet<>(); for (int num : nums) { if (!seen.add(num)) { // add returns false if already present return true; } } return false; // no duplicates found } }
Python โ€” One-pass set
class Solution: def containsDuplicate(self, nums: list[int]) -> bool: seen = set() for num in nums: if num in seen: # O(1) membership check return True seen.add(num) return False # no duplicates
06
Section Six ยท Analysis

Complexity Analysis

Approach Time Space Trade-off
Brute Force O(nยฒ) O(1) No extra memory, but too slow for n = 10โต
Sort + Linear Scan O(n log n) O(1)* In-place sort mutates input; duplicates become adjacent
HashSet โ† optimal O(n) O(n) One pass, O(1) per lookup. Space for the set.
Why not sorting?:
  • Sorting gives O(n log n) and lets you check adjacent elements for duplicates โ€” but it mutates the input array (or costs O(n) to copy first).
  • The HashSet approach is faster at O(n), doesn't modify the input, and exits early when a duplicate is found.
  • The trade-off is O(n) extra memory for the set. *O(1) space for sort assumes in-place; O(n) if you copy first to preserve the original.
07
Section Seven ยท Edge Cases

Edge Cases & Pitfalls

Case Input Why It Matters
Negative numbers [-1, -2, -3, -1] HashSet handles negatives โ€” hash function works the same for all integers.
Zeros [0, 0] Two zeros are duplicates. The set catches 0 on the second occurrence.
All duplicates [5, 5, 5, 5] Detected immediately at i=1 โ€” the set already contains 5 from i=0.
Single element [1] Minimum valid input. A single element can never have a duplicate โ†’ false.
Large values [10โน, -10โน, 10โน] No overflow concern โ€” we compare values, never compute sums. HashSet handles extreme ints.
No duplicates [1, 2, 3, 4, 5] Worst case โ€” we scan the entire array, build a set of size n, and return false.
โš  Common Mistake: Using set.contains() followed by set.add() as two separate calls. In Java, HashSet.add() already returns false if the element was already present โ€” so if (!seen.add(num)) is a single-call shortcut that checks and inserts atomically, avoiding a redundant hash computation.

โ† Back to Arrays & Hashing problems