287 - Find the Duplicate Number
Wednesday, 16 September 2026
Read the array as a linked list, then Floyd's cycle detection - the duplicate is the node where the cycle starts, not where the pointers meet.
Problem
Given an array of integers nums containing n + 1 integers where each integer is in the range [1, n] inclusive.
There is only one repeated number in nums, return this repeated number.
You must solve the problem without modifying the array nums and use only constant extra space.
Input: nums = [1,3,4,2,2]
Output: 2
Input: nums = [3,1,3,4,2]
Output: 3
Input: nums = [3,3,3,3,3]
Output: 3 Constraints:
1 <= n <= 10^5nums.length == n + 11 <= nums[i] <= n- All the integers in
numsappear only once except for precisely one integer which appears two or more times
Approach
nums = [1, 3, 4, 2, 2]
i: 0 1 2 3 4
following i -> nums[i] from 0:
0 -> 1 -> 3 -> 2 -> 4
^ |
+----+
tail 0 -> 1 -> 3
cycle 2 -> 4 -> 2
entrance 2, which is the duplicate nums[4] is 2 and nums[2] is 4, so the loop is just those two. Node 3 sits on the tail, not
in the cycle — it is the last node before the entrance, which is a different thing and the easy one
to mislabel when sketching these.
Floyd’s Cycle Detection
- Phase one: finds some node in the cycle. Move
sone step per iteration andftwo. Once both are inside the cycle the gap closes by one each step, so they must land on the same node. - Phase two: converts that into the entrance. Reset
sto the head and advance both one step at a time; they meet again exactly at the cycle’s start.
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int s = 0, f = 0;
do {
s = nums[s];
f = nums[nums[f]];
} while (s != f);
s = 0;
while (s != f) {
s = nums[s];
f = nums[f];
}
return s;
}
}; - time:
O(n)— phase one is at mosta + citerations, phase two at mosta - space:
O(1)— two indices, and the array is never written to
Cyclic Sort
Every value is in [1, n], so value v has a home at index v - 1. Walk the array and keep
swapping the current value to its home until the slot already holds its own value, then move on. When
the placing finishes, every index holds its matching value except where the duplicate forced a
collision, so one scan finds it.
int findDuplicate(vector<int>& nums) {
const int n = nums.size();
int i = 1;
while (i <= n) {
int corr = nums[i - 1];
if (nums[corr - 1] != corr) {
swap(nums[corr - 1], nums[i - 1]);
} else {
i++;
}
}
for (int j = 1; j <= n; j++)
if (nums[j - 1] != j) return nums[j - 1];
return -1;
}