题目:
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.
思路:
1)理论证明:鸽笼原理,说n个东西放到m个容器中,如果n > m,那么必然有一个容器包含多于一个东西。用反证法证明:假设每个容器里面的东西至多有一个,那么m个容器中的东西至多有m < n个,与一共有n个东西相矛盾,所以假设不成立,鸽笼原理成立。
2)代码实现:由于不允许对数组进行排序,也不允许使用额外的空间,所以少于O(n^2)的时间复杂度的解法的唯一可能性就是二分查找。我们使用二分查找先确定一个中间值mid,然后统计整个数组,看比mid小的数是否比mid多,如果多的话,说明重复的值就在[left, mid - 1]之间,否则就在[mid + 1, right]之间。
代码:
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int len = nums.size();
int left = 1, right = len;
while(left <= right) {
int mid = left + (right - left) / 2;
int cnt = 0;
for(int i = 0; i < len; ++i) {
if(nums[i] <= mid) {
++cnt;
}
}
if(cnt <= mid) {
left = mid + 1;
}
else {
right = mid - 1;
}
}
return left;
}
};