287. 寻找重复数
2020-05-26 本文已影响0人
geaus
题目描述
给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。
示例:
输入: [1,3,4,2,2]
输出: 2
示例 2:
输入: [3,1,3,4,2]
输出: 3
说明:
不能更改原数组(假设数组是只读的)。
只能使用额外的 O(1) 的空间。
时间复杂度小于 O(n2) 。
数组中只有一个重复的数字,但它可能不止重复出现一次。
解题思路
- 二分法
假定在某一个值i,如果i前面有重复的数那么一定会有cnt(i)>i,这里cnt(i)表示到值i时个元素个数;否则的话重复数字一定>i;这样就可以在i之后查找重复数字。
int findDuplicates(vector<int>& nums){
int n = nums.size();
int l=1, r=n-1;
int ans=-1;
while(l<=r){
int mid = (l+r)>>1;
int cnt=0;
for(int i=0;i<n;i++){
cnt += nums[i]<=mid;
}
if(cnt<=mid){
l = mid+1;
}else{
ans = mid;
r = mid-1;
}
}
return ans;
}
- floyd环的思路
设置fast,slow指针,fast指针每次跳两步,slow指针每次跳一步。由于数组中存在重复数字,所以有环。最终两个指针会相遇。这时,将slow指针拨回0下标,然后两个指针每次跳一步,最终相遇的位置即为环的入口(重复数字)。
int findDuplicates(vector<int>& nums){
int slow=0, fast=0;
do{
slow = nums[slow];
fast = nums[nums[fast]];
} while(slow!=fast);
slow = 0;
while(slow!=fast){
slow = nums[slow];
fast = nums[fast];
}
return fast;
}