Problem:
Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.
Note:
- You must not modify the array (assume the array is read only).
- You must use only constant, O(1) extra space.
- Your runtime complexity should be less than O(n2).
- There is only one duplicate number in the array, but it could be repeated more than once.
Here is a O(nlogn) algorithm. The key idea is to use binary search. Every time we will make a guess, it is the mid value of the current range of candidates. We then compute the following values:
count_lt_mid = #{x: x < guessed value}
count_eq_mid = #{x: x == guessed value}
if count_eq_mid > 1, we need to return guessed value (obvious).
The key observation here is if count_eq_mid >= guessed value, the duplicated value must be smaller than guessed value because [1 .. guessed value - 1] has only "guessed value - 1" possibilities.
class Solution { public: int findDuplicate(vector<int>& nums) { return helper(nums, 1, nums.size()-1); } int helper(vector<int>& nums, int start, int end) { if (start == end) return start; int guess = (start + end) / 2; int count_lt_mid = 0; int count_eq_mid = 0; for (int i = 0; i < nums.size(); ++i) { if (nums[i] < guess) ++count_lt_mid; if (nums[i] == guess) ++count_eq_mid; } if (count_eq_mid > 1) return guess; if (count_lt_mid >= guess) return helper(nums, start, guess-1); if (count_lt_mid < guess) return helper(nums, guess+1, end); return -1; } };
No comments:
Post a Comment