Skip to content

Fast & Slow — Find the Duplicate Number ​

↗ LeetCode: Find the Duplicate Number · Medium · pattern chapter →

Asked atMetaAmazonGoogleMicrosoft

Given an array nums of n + 1 integers where each is in [1, n], there is exactly one duplicate. Return it. Constraints: don't modify nums; use O(1) extra space.

Example 1 — nums = [1,3,4,2,2] → 2Example 2 — nums = [3,1,3,4,2] → 3Example 3 — nums = [1,1] → 1

Constraints — 1 ≤ n ≤ 10⁵; 1 ≤ nums[i] ≤ n. Brute HashSet is O(n) time + O(n) space (breaks the "no modify + O(1) space" constraint). Floyd's cycle detection on the value-index graph is O(n) time + O(1) space — ~10⁶ pointer chases at n=10⁵.

Progressive Hints
Try to solve it yourself first. Reveal hints only when stuck — each hint is progressively more specific.
---
⏱️Interview timer00:00
Practice under interview pressure. Start when you begin reading; stop when you finish. Save best only when you had a full working solution.
Target for interview: Medium = 20-25 min · Hard = 30-40 min · Best time persists on this device only.

Approach 1 — Sort ​

O(n log n) time, O(1) if sort in place — but modifies input (disallowed).

Approach 2 — Hash set ​

O(n) time, O(n) space — disallowed by spec.

Approach 3 — Binary search on value ​

Intuition. Binary search on [1, n] for the duplicate. For mid m, count how many nums are ≤ m. If count > m, duplicate is in [1, m]; else [m+1, n].

java
int findDuplicateBS(int[] nums) {
    int lo = 1, hi = nums.length - 1;
    while (lo < hi) {
        int mid = lo + (hi - lo) / 2;
        int cnt = 0;
        for (int x : nums) if (x <= mid) cnt++;
        if (cnt > mid) hi = mid;
        else lo = mid + 1;
    }
    return lo;
}

Complexity — Time O(n log n); Space O(1).


Approach 4 — Floyd's tortoise/hare on implicit list (canonical) ​

Insight. Treat nums[i] as "next(i)". Since every value is in [1, n] and there are n+1 positions, this functional graph must contain a cycle, and the cycle entry is the duplicate value.

Why entry = duplicate. Two different indices i1 ≠ i2 both point to the duplicate → the duplicate is the "merge point" of two paths in the functional graph, i.e., the cycle entry.

Same Floyd's algorithm as Linked List Cycle II: find meeting point; reset one pointer to start; walk both at speed 1; they meet at the cycle entry.

java
int findDuplicate(int[] nums) {
    int slow = nums[0], fast = nums[0];
    do { slow = nums[slow]; fast = nums[nums[fast]]; } while (slow != fast);
    slow = nums[0];
    while (slow != fast) { slow = nums[slow]; fast = nums[fast]; }
    return slow;
}
Execution Trace
Floyd — nums=[1,3,4,2,2]
slowfast1031422324s = 1f = 1
Step 1 / 5both at nums[0]=1

Complexity — Time O(n); Space O(1).


Try it yourself ​

Complexity summary ​

ApproachTimeSpaceInterview grade
SortO(n log n)O(1)modifies input
Hash setO(n)O(n)violates space limit
Binary search on valueO(n log n)O(1)acceptable
Floyd's on implicit listO(n)O(1)canonical for the constraints

When to use which ​

  • Constraint: don't modify + O(1) space → Floyd's.
  • "Multiple duplicates possible" → hash-based counting or bit manipulation.
  • "Return every duplicate" → mark visited via nums[abs(v)-1] *= -1 (modifies input).
  • Generalization: "smallest missing positive" → different problem (in-place index marking).
✨AI Study CompanionBeta
Was this page helpful?

Released under MIT license.

💡 Quick shortcuts
H HintsR Run JavaA AI Help