Welcome to Subscribe On Youtube
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.
Follow up:
- 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 { #[allow(dead_code)] 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 } }