Last Updated: March 29, 2026
We have an array that should contain every integer from 1 to n exactly once, but something went wrong. One number appears twice, and because of that, another number is missing entirely. Our job is to find both: the duplicate and the missing number.
The constraint 1 <= nums[i] <= nums.length is important. It tells us every value in the array is within the range [1, n], which means we can use the values themselves as indices. This is the key observation that unlocks the most elegant solutions.
A brute force approach would count occurrences of every number. But we can do better by exploiting the relationship between the values and the index range [1, n]. Techniques like sorting, hashing, sum/sum-of-squares math, and index marking all become viable because of this tight value-to-index mapping.
2 <= nums.length <= 10^4 — With n up to 10,000, O(n^2) means 100 million operations, which is borderline. O(n log n) and O(n) approaches are both comfortable.1 <= nums[i] <= nums.length — Every value maps directly to a valid index in the range [1, n]. This enables index-marking techniques and mathematical approaches.The most straightforward way to spot a duplicate is to sort the array first. Once sorted, duplicate numbers sit next to each other, and a gap in the sequence reveals the missing number. This is the approach you'd naturally reach for if someone handed you a shuffled deck of numbered cards and asked you to find the repeated and missing one.
nums[i] == nums[i-1], we found the duplicate.nums[i] > nums[i-1] + 1, the missing number is nums[i-1] + 1.missing is still not found, the missing number must be n.[duplicate, missing].Input:
After sorting (already sorted in this case), we scan adjacent pairs:
nums[1]=2 == nums[0]=1 — no match, no gapnums[2]=2 == nums[1]=2 — duplicate found! duplicate = 2nums[3]=4 > nums[2]=2 + 1 — gap! missing = 3Result:
This approach works but sorting gives us more information than we need. What if we just counted how many times each number appears?
Instead of sorting to detect duplicates and gaps, we can just count how many times each number appears. Build a frequency map in one pass, then scan numbers 1 through n. The number with count 2 is the duplicate, and the number with count 0 is the missing one.
This is the approach most people would write in production. It's clean, obvious, and hard to get wrong.
Since every number from 1 to n should appear exactly once, any deviation from a count of 1 reveals the error. A count of 2 means that number was duplicated, and a count of 0 means that number was overwritten and is now missing. The hash map lets us compute all counts in O(n), and the second pass over [1, n] lets us identify both anomalies.
[duplicate, missing].The hash map uses O(n) extra space. Since every value maps to a valid index in [1, n], can we use the array itself as our visited tracker?
Since every value in the array is between 1 and n, we can use each value as an index into the array itself. When we visit a number, we negate the value at the corresponding index to "mark" it as seen. If we try to mark an index that's already negative, we've found the duplicate. After the marking pass, the index that still holds a positive value corresponds to the missing number.
This is essentially using the input array as a boolean visited array, with the sign bit serving as the flag. It's O(n) time and O(1) extra space.
The sign of nums[i] encodes whether the number i+1 has been "seen" in the array. In a correct array [1, n], every index from 0 to n-1 would get negated exactly once. When one number is duplicated, its corresponding index gets negated twice (the second time, it's already negative, revealing the duplicate). And because the missing number was never in the array, its corresponding index never gets negated, staying positive.
abs(nums[i]) - 1.nums[targetIndex]. If it's already negative, then abs(nums[i]) is the duplicate.nums[targetIndex] to mark it as visited.nums[index] > 0 corresponds to the missing number (which is index + 1).[duplicate, missing].