题目: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.
- 给定一个长度为 n+1 的数组,里面只有 1...n 的数值。可见必然有一个元素的值是重复出现的。假设只有最多只有一个元素的值会重复出现,求出重复的那个值。
1. 不能修改原数组
2. 只用固定空间,空间使用为 O(1)
3. 时间复杂度要小于 O(n*2)
class Solution
public:
int findDuplicate(vector<int>& nums) {
int n=nums.size();
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
{
if(nums[i]==nums[j])
return nums[i];
}
}
};
solution2:在solution1的基础上优化,不需要遍历所有的数去比较是否有相同的,采用二分查找法,统计比中间的数小的个数,如果大于中间的数值,证明重复的数在其左边,否则在其右边。
遇到的问题:思路懂了,但是写不出来。第一不知如何返回,返回什么,也就是循环结束条件即返回值不太明白。第二,写出来的还有问题
研究了别人的代码后,学到当while(min<=max)条件不满足退出while循环的前一次循环是min=max,进入循环后对max做了修改,所以不再满足循环条件,因此输出min的值即要找的数。
class Solution
{
public:
int findDuplicate(vector<int>& nums)
{
int n=nums.size();
int min=0;
int max=n-1;
while(min<=max)
{ int mid=min+(max-min)/2;
int count=0;
for(int i=0;i<n;i++)
{
if(nums[i]<=mid)
count++;
}
if(count>mid)
max=mid-1;
else
min=mid+1;
}
return min;
}
};
solution3:映射法: