Skip to content

Contains Duplicate

Problem Statement

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.

Examples

Example 1

text
Input: nums = [1, 2, 3, 1]
Output: true
Explanation: The element 1 appears twice.

Example 2

text
Input: nums = [1, 2, 3, 4]
Output: false
Explanation: All elements are distinct.

Example 3

text
Input: nums = [1, 1, 1, 3, 3, 4, 3, 2, 4, 2]
Output: true
Explanation: Multiple elements appear more than once.

Visual Explanation

Contains Duplicate Process

Multiple Approaches

Approach 1: Hash Set (Optimal)

  • Use a set to track seen elements
  • O(1) average lookup time

Approach 2: Sorting

  • Sort and check adjacent elements
  • Modifies the array

Approach 3: Brute Force

  • Compare every pair
  • O(n^2) time - not recommended

Solution

python
def containsDuplicate(nums: list[int]) -> bool:
    """
    Check if array contains any duplicates using a hash set.

    Time Complexity: O(n)
    Space Complexity: O(n)
    """
    seen = set()

    for num in nums:
        if num in seen:
            return True
        seen.add(num)

    return False
java
public boolean containsDuplicate(int[] nums) {
    Set<Integer> seen = new HashSet<>();

    for (int num : nums) {
        if (seen.contains(num)) {
            return true;
        }
        seen.add(num);
    }

    return false;
}

Complexity (Hash Set): Time O(n) · Space O(n)

  • Time: Single pass with O(1) average hash set lookup/insert operations per element
  • Space: Worst case stores all n elements when no duplicates exist
python
# One-liner using set length comparison
def containsDuplicate_oneliner(nums: list[int]) -> bool:
    """
    If set has fewer elements than array, duplicates exist.

    Time Complexity: O(n)
    Space Complexity: O(n)
    """
    return len(nums) != len(set(nums))


# Sorting approach (modifies array)
def containsDuplicate_sorting(nums: list[int]) -> bool:
    """
    Sort and check adjacent elements.

    Time Complexity: O(n log n)
    Space Complexity: O(1) if in-place sort, O(n) otherwise
    """
    nums.sort()

    for i in range(1, len(nums)):
        if nums[i] == nums[i - 1]:
            return True

    return False


# Brute force (for reference - do not use)
def containsDuplicate_bruteforce(nums: list[int]) -> bool:
    """
    Check every pair - NOT RECOMMENDED.

    Time Complexity: O(n^2)
    Space Complexity: O(1)
    """
    n = len(nums)
    for i in range(n):
        for j in range(i + 1, n):
            if nums[i] == nums[j]:
                return True
    return False

Complexity (One-liner): Time O(n) · Space O(n)

  • Time: O(n) to build the set, O(1) for length comparisons
  • Space: Creates a complete set of up to n elements; no early termination benefit

Complexity (Sorting): Time O(n log n) · Space O(1) to O(n)

  • Time: Dominated by sort operation; linear scan afterward is O(n)
  • Space: O(1) if in-place sort allowed (Timsort uses O(n) auxiliary space internally in Python)

Complexity (Brute Force): Time O(n^2) · Space O(1)

  • Time: Nested loops compare each pair; n*(n-1)/2 comparisons total
  • Space: No additional data structures used

Comparison of Approaches

ApproachTimeSpaceProsCons
Hash SetO(n)O(n)Fastest, early terminationExtra space
One-linerO(n)O(n)ConciseBuilds full set first
SortingO(n log n)O(1)*No extra spaceModifies array
Brute ForceO(n^2)O(1)SimpleToo slow

*Note: Python's sort uses O(n) space internally

Step-by-Step Trace (Hash Set)

For nums = [1, 2, 3, 1]:

IndexValueseen (before)In seen?Action
01{}NoAdd 1
12{1}NoAdd 2
23{1, 2}NoAdd 3
31{1, 2, 3}YesReturn True

Complexity Analysis

MetricComplexity
TimeO(n) - Single pass, O(1) hash operations
SpaceO(n) - Worst case stores all elements

Sorting Approach

MetricComplexity
TimeO(n log n) - Dominated by sorting
SpaceO(1) to O(n) - Depends on sort implementation

Edge Cases

  1. Empty array: [] -> Return false
  2. Single element: [1] -> Return false
  3. Two same elements: [1, 1] -> Return true
  4. Two different elements: [1, 2] -> Return false
  5. All same elements: [5, 5, 5, 5] -> Return true
  6. Large array, no duplicates: [1, 2, ..., n] -> Return false
  7. Negative numbers: [-1, -1] -> Return true

Variations

Contains Duplicate II (Within K Distance)

python
def containsNearbyDuplicate(nums: list[int], k: int) -> bool:
    """
    Return true if nums[i] == nums[j] and abs(i-j) <= k.
    """
    index_map = {}

    for i, num in enumerate(nums):
        if num in index_map and i - index_map[num] <= k:
            return True
        index_map[num] = i

    return False

Complexity: Time O(n) · Space O(min(n, k))

  • Time: Single pass with O(1) hash map operations per element
  • Space: Map stores at most min(n, k+1) entries since we track indices within distance k

Contains Duplicate III (Within K Distance and T Value Difference)

python
def containsNearbyAlmostDuplicate(nums: list[int], k: int, t: int) -> bool:
    """
    Return true if nums[i] and nums[j] differ by at most t
    and indices differ by at most k.
    Uses bucket sort concept.
    """
    if t < 0:
        return False

    buckets = {}
    bucket_size = t + 1

    for i, num in enumerate(nums):
        bucket_id = num // bucket_size

        # Check same bucket
        if bucket_id in buckets:
            return True

        # Check adjacent buckets
        if bucket_id - 1 in buckets and num - buckets[bucket_id - 1] <= t:
            return True
        if bucket_id + 1 in buckets and buckets[bucket_id + 1] - num <= t:
            return True

        buckets[bucket_id] = num

        # Remove old buckets outside window
        if i >= k:
            old_bucket = nums[i - k] // bucket_size
            del buckets[old_bucket]

    return False

Complexity: Time O(n) · Space O(min(n, k))

  • Time: Single pass; bucket operations (insert, delete, lookup) are O(1)
  • Space: At most k+1 buckets maintained due to sliding window cleanup

Common Mistakes

  1. Using list instead of set - O(n) lookup instead of O(1)
  2. Not considering empty arrays - Handle edge case
  3. Modifying input when not allowed - Sorting changes the array
  4. Using brute force - O(n^2) will fail on large inputs
Contains Duplicate II (LeetCode 219)

Problem: Check if there are two distinct indices i and j where nums[i] == nums[j] AND abs(i - j) <= k.

Key Insight: Use hash map to store most recent index of each number, check distance on duplicates.

Approach: For each number, if already in map and distance <= k, return true. Update map with current index.

Complexity: O(n) time, O(min(n, k)) space

Contains Duplicate III (LeetCode 220)

Problem: Check if there are indices i, j where abs(i - j) <= k AND abs(nums[i] - nums[j]) <= t.

Key Insight: Use bucket sort concept - numbers in same or adjacent buckets could satisfy condition.

Approach: Create buckets of size t+1. Check same bucket and adjacent buckets. Remove old buckets outside window k.

Complexity: O(n) time, O(min(n, k)) space

Find the Duplicate Number (LeetCode 287)

Problem: Find duplicate in array of n+1 integers where each is in [1, n], without modifying array.

Key Insight: Treat array as linked list where value points to next index. Use Floyd's cycle detection.

Approach: Fast/slow pointers to find cycle, then find cycle entrance (the duplicate).

Complexity: O(n) time, O(1) space

Two Sum (LeetCode 1)

Problem: Find two indices whose values sum to target.

Key Insight: Use hash map to check for complement in O(1).

Approach: For each number, check if (target - num) exists in map. If not, add current number to map.

Complexity: O(n) time, O(n) space

Key Takeaways

  • Hash sets provide O(1) average lookup for duplicate detection
  • The one-liner len(nums) != len(set(nums)) is Pythonic but less efficient for early termination
  • Consider trade-offs between time, space, and whether input modification is allowed
  • This is a fundamental pattern used in many other problems