# 287. Find the Duplicate Number

## Description

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 uses only constant extra space.

Example 1:

Input: nums = [1,3,4,2,2]
Output: 2


Example 2:

Input: nums = [3,1,3,4,2]
Output: 3


Constraints:

• 1 <= n <= 105
• nums.length == n + 1
• 1 <= nums[i] <= n
• All the integers in nums appear only once except for precisely one integer which appears two or more times.

• How can we prove that at least one duplicate number must exist in nums?
• Can you solve the problem in linear runtime complexity?

## Solutions

Solution 1: Binary Search

We can observe that if the number of elements in $[1,..x]$ is greater than $x$, then the duplicate number must be in $[1,..x]$, otherwise the duplicate number must be in $[x+1,..n]$.

Therefore, we can use binary search to find $x$, and check whether the number of elements in $[1,..x]$ is greater than $x$ at each iteration. This way, we can determine which interval the duplicate number is in, and narrow down the search range until we find the duplicate number.

The time complexity is $O(n \times \log n)$, where $n$ is the length of the array $nums$. The space complexity is $O(1)$.

• class Solution {
public int findDuplicate(int[] nums) {
int l = 0, r = nums.length - 1;
while (l < r) {
int mid = (l + r) >> 1;
int cnt = 0;
for (int v : nums) {
if (v <= mid) {
++cnt;
}
}
if (cnt > mid) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
}
}

• class Solution {
public:
int findDuplicate(vector<int>& nums) {
int l = 0, r = nums.size() - 1;
while (l < r) {
int mid = (l + r) >> 1;
int cnt = 0;
for (int& v : nums) {
cnt += v <= mid;
}
if (cnt > mid) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
}
};

• class Solution:
def findDuplicate(self, nums: List[int]) -> int:
def f(x: int) -> bool:
return sum(v <= x for v in nums) > x

return bisect_left(range(len(nums)), True, key=f)


• func findDuplicate(nums []int) int {
return sort.Search(len(nums), func(x int) bool {
cnt := 0
for _, v := range nums {
if v <= x {
cnt++
}
}
return cnt > x
})
}

• function findDuplicate(nums: number[]): number {
let l = 0;
let r = nums.length - 1;
while (l < r) {
const mid = (l + r) >> 1;
let cnt = 0;
for (const v of nums) {
if (v <= mid) {
++cnt;
}
}
if (cnt > mid) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
}


• /**
* @param {number[]} nums
* @return {number}
*/
var findDuplicate = function (nums) {
let l = 0;
let r = nums.length - 1;
while (l < r) {
const mid = (l + r) >> 1;
let cnt = 0;
for (const v of nums) {
if (v <= mid) {
++cnt;
}
}
if (cnt > mid) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
};


• impl Solution {
pub fn find_duplicate(nums: Vec<i32>) -> i32 {
let mut left = 0;
let mut right = nums.len() - 1;

while left < right {
let mid = (left + right) >> 1;
let cnt = nums
.iter()
.filter(|x| **x <= (mid as i32))
.count();
if cnt > mid {
right = mid;
} else {
left = mid + 1;
}
}

left as i32
}
}