可以认为有两个数组,一个是原数组,一个是1-n的范围数组(无重复),每次对low-high的范围数组做二分,取中间数mid,然后去原数组中统计小于等于mid的数目,如果大于mid(如果无重复,那么应该小于等于mid),说明重复的那个数字在1-mid之间,结合范围即在(low-mid之间)。否则说明小于1-mid之间无重复,重复的应该在mid+1到hight之间
int findDuplicate(vector<int>& nums) {
int n=nums.size()-1;
int low=1; //最小数为1
int high=n; //最大数为n-1,数组范围为1-n,找中间数
int mid;
while(low<high){
mid=(low+high)/2; //low,high是在1-n的数组上,而不是原数组上
int count=0;
for(int num:nums){
if(num<=mid) count++;
}
if(count>mid) high=mid;
else low=mid+1;
}
return low;
}
int findDuplicate(vector<int>& nums)
{
if (nums.size() > 1)
{
int slow = nums[0];
int fast = nums[nums[0]];
while (slow != fast)
{
slow = nums[slow]; //一次走一步
fast = nums[nums[fast]]; //一次走两步
}
fast = 0; //快指针回到起点,慢指针在相遇点,两个一起走一步
while (fast != slow)
{
fast = nums[fast];
slow = nums[slow];
}
return slow;
}
return -1;
}
解释参考:https://www.cnblogs.com/jimmycheng/p/7519870.html
假设重复的数字是x,对应的两个下标分别为a和b,a和b也在数组里,当到a时,下一步会到x,经过一段时间后遍历到b时还会到x,一次循环。即环的起点就是那个重复的元素