Find the Duplicate Number – Solution & Complexity
Solution Walkthrough
1. Start from the constraints, not from code
- Sorting would either modify the array or require copying it first.
- A hash set finds the duplicate quickly, but it uses
O(n)extra memory. - The intended trick is to treat each index as a node with one outgoing edge:
i -> nums[i]. Because values stay in[1, n], following pointers from index0must eventually enter a cycle, and the duplicate value is the cycle's entrance.
2. Warm up with a disallowed hash-set solution
- Scan the array and remember values seen so far.
- The first value you encounter twice is the answer.
- This is correct and runs in
O(n)time, but it violates the constant-space requirement, so it is only a warm-up.
3. Why Floyd's cycle detection works here
- Think of index
ias a node whose next pointer isnums[i]. Since everynums[i]is between1andn, once you move from index0, you stay inside the node set1..n. - There are
n + 1indices but onlynpossible next-node values, so following pointers from0must eventually revisit a node: a cycle exists. - The duplicate value is exactly the first node with two incoming edges on that reachable path, so it is the cycle entrance.
- Floyd's algorithm first finds any meeting point inside the cycle, then resets one pointer to the start and advances both one step at a time; they meet at the entrance.
4. Apply Floyd's tortoise-and-hare algorithm
- Start
slowone step from the start andfasttwo steps from the start. - Move
slowby one edge andfastby two edges until they meet inside the cycle. - Then reset a
finderpointer to index0, movefinderandslowone step at a time, and return where they meet. That meeting value is the duplicate number.
5. Dry run on nums = [1,3,4,2,2]
The pointer graph is 0 -> 1 -> 3 -> 2 -> 4 -> 2 -> ..., so the cycle starts at value 2.
Phase 1: find a meeting point inside the cycle
| step | slow | fast |
|---|---|---|
| start | 1 | 3 |
| 1 | 3 | 4 |
| 2 | 2 | 4 |
| 3 | 4 | 4 |
They first meet at value 4, which is inside the cycle but is not necessarily the duplicate.
Phase 2: find the cycle entrance
| step | finder | slow |
|---|---|---|
| start | 0 | 4 |
| 1 | 1 | 2 |
| 2 | 3 | 4 |
| 3 | 2 | 2 |
Now both pointers meet at 2, so the duplicate number is 2.
6. Common mistakes
- Returning the first
slow == fastmeeting point directly. That point is somewhere inside the cycle, not always the duplicate value itself. - Starting both pointers at
nums[0]; that can make them appear to meet immediately before any real progress. Use one step vs. two steps at initialization. - Mixing up indices and values, or subtracting
1as if the graph were zero-based on1..n. The values already are valid next indices for this construction. - Using sorting or a hash set in the final answer, which breaks the read-only or constant-space constraints.
7. Edge cases to test mentally
- Smallest valid input:
[1,1]immediately forms a one-node cycle, so the answer is1. - A duplicate may appear three or more times, such as
[2,5,9,6,9,3,8,9,7,1,4]; the entrance is still9. - The duplicate value can appear in the first array slot, the last slot, or only after a long tail before the cycle begins.
- The answer is the repeated value, not the index of one occurrence.
8. Final full solution and complexity
Treating the array as a functional graph lets Floyd's cycle detection find the duplicate in O(n) time with O(1) extra space, without modifying nums.