2Brute2Best
🔥0

Contains Duplicate

Easy·LeetCode #217Basic Anchor
LeetCode
30-Second Mental ModelHash Set membership (seen-before check)
Complexity:O(N²)→O(N)
Key Insight

Walk the array once and keep every value you have passed in an unordered_set. Before adding x, the set already tells you in O(1) whether x was seen. If it was, you found a duplicate.

Core Validity Invariant

nums[i] is a duplicate exactly when it is already in seen — that means it appeared at some earlier index.

01

Problem

You are given an integer array nums.

Return true if some value appears at least twice in the array. Return false if every value is different.

Input

An integer array nums.

Output

true if any value repeats, otherwise false.

Example 1
Input: nums = [1, 2, 3, 1]
Output: true

The value 1 appears at index 0 and again at index 3.

Example 2
Input: nums = [1, 2, 3, 4]
Output: false

All four values are different.

Example 3
Input: nums = [1, 1, 1, 3, 3, 4, 3, 2, 4, 2]
Output: true

Several values repeat. Finding one repeat is enough.

Constraints
  • • 1 ≤ nums.length ≤ 10^5
  • • −10^9 ≤ nums[i] ≤ 10^9
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    Do I need to know which value repeats, or how many times, or only whether one repeats?

  2. 2.

    Does it matter how far apart the two equal values are?

  3. 3.

    If I walk left to right, what do I need to remember about the values I have already passed?

  4. 4.

    If the array were sorted, where would two equal values be?

  5. 5.

    Am I allowed to change the array? Do I care about extra memory?

03

Brute force approach

04

Better approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceCheck every pair (i, j) for equal valuesO(N²)O(1)
BetterSort; equal values become neighboursO(N log N)O(1)
OptimalInsert each value into a set; a failed insert means a duplicateO(N)O(N)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “appears at least twice”We only need "have I seen this before?" — a membership question.
  • “return true / false”No counts or positions needed → a set is enough, not a map.
  • “any two positions (no distance limit)”Remember **every** earlier value, not just a window of recent ones.
Have I seen this value before?+yes / no answer+any distance→Hash Set membership (seen-before check)

This is the anchor of the set-membership sub-pattern: put values in a set, and each "is x present?" question costs O(1). Longest Consecutive Sequence asks the same question about x − 1 and x + 1 instead of x itself, and First Missing Positive asks it about 1, 2, 3, …. Contains Duplicate II adds a distance limit k, which turns the set into a sliding window of the last k values — this problem has no such limit.

10

Don't make this mistake

Solving Contains Duplicate II instead
✗ seen.insert(nums[i]); if (i >= k) seen.erase(nums[i - k]);
✓ // keep every value; never erase if (!seen.insert(nums[i]).second) return true;

This is a pattern-confusion trap. Contains Duplicate II only counts duplicates at most k apart, so it keeps a window of the last k values. Here there is no distance limit: two equal values at index 0 and index 99999 still count. Erasing old values makes you miss them.

Using a map of counts when a set is enough
✗ unordered_map<int, int> cnt; for (int x : nums) cnt[x]++; for (auto& [v, c] : cnt) if (c > 1) return true;
✓ unordered_set<int> seen; for (int x : nums) if (!seen.insert(x).second) return true;

Counts are not needed — only "seen or not". The map version also always reads the whole array and then loops again, instead of stopping at the first repeat. Pick the smallest structure that answers the question.

Comparing non-neighbours after sorting, or forgetting to sort
✗ for (int i = 1; i < n; i++) if (nums[i] == nums[i - 1]) return true; // unsorted
✓ sort(nums.begin(), nums.end()); for (int i = 1; i < n; i++) if (nums[i] == nums[i - 1]) return true;

The neighbour check is only correct because sorting puts equal values together. On the unsorted [1, 2, 3, 1] no two neighbours are equal, so it wrongly returns false.

Starting the brute-force inner loop at j = 0
✗ for (int j = 0; j < n; j++) if (nums[i] == nums[j]) return true;
✓ for (int j = i + 1; j < n; j++) if (nums[i] == nums[j]) return true;

With j = 0, the pair i == j compares an element with itself, so every array looks like it has a duplicate.

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like Arrays & Hashing translate into production architectures and low-level memory mechanics.