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 } } 

All Problems

All Solutions