Question:
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.
This is a bad solution....but it works....
public class Solution {
public int findDuplicate(int[] nums) {
int n=nums.length;
int i=0;
int j=0;
if(n<=2)
return nums[0];
int ans=0;
for(i=0;i<=n-2;i++)
{
for(j=i+1;j<=n-1;j++)
{
if(nums[i]-nums[j]==0){
ans=nums[i];break;}
}
}
return ans;
}
}
快慢指针找环 参考了这个~http://www.jianshu.com/p/ce7f035daf74 写的好清楚
public class Solution {
public int findDuplicate(int[] nums) {
int fast=0;
int slow=0;
if(nums == null || nums.length < 2) {
return -1;
}
while(true)
{
slow=nums[slow];
fast=nums[nums[fast]];
if(slow==fast)
break;
}
fast=0;
while(true)
{
slow=nums[slow];
fast=nums[fast];
if(slow==fast)
break;
}
return fast;
}
}
还可以用二分法做。。据说也很棒!我觉得有点难度,巧妙用了nums[i]和i,抽屉原理
int n=nums.length;
int low=0;
int high=n-1;
while(low<high)
{
int mid=(high-low)/2+low;
int c=count(nums,mid);
if(c<=mid) {
low = mid+1;
} else {
high = mid;
}
}
return low;
}
public int count(int nums[], int mid)
{
int ans=0;
for(int i=0;i<=nums.length-1;i++)
{
if(nums[i]<=mid)
ans++;
}
return ans;