题目:
在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组。例如,如果输入长度为8的数组{2,3,5,4,3,2,6,7,},那么对应的输出是重复的数字2或者3.
这一题貌似和上一种办法差不多,但是不能修改数组,
对于上一种办法的前三种都ok,都可以用,但是第四种办法不能用。
在这里我们就不说前三种。
我们把从1~n的数字从中间的数字m分为两部分,前面一半为1~m,后面一半为m+1~n。如果1~m的数字的数目超过m,那么这一半的区域里一定包含重复的数字;否则,另一半m+1~n的区间里一定包含重复的数字,我们可以继续接着一分为二,直到找到一个重复的数字,这种方法类似于二分法,只是多一步统计区间里的数字数目。
Eg:
int getDuplication(const int *numbers,int length)
{
if(numbers==nullptr||length<=0)
return -1;
int start=1;
int end=length-1;
while(end>=start)
{
int middle =((end-start)>>1)+start;
int count =countRange(numbers.length,start,middle);
if(end == start)
{
if(count >1)
return start;
else
break;
}
if(count>(middle-start +1))
end=middle;
else
start=middle+1;
}
return -1;
}
int countRange (const int *numbers;int length;int start,int end)
{
if(numbers ==nullptr)
return 0;
int count=0;
if(int i=0;i<length;i++)
if(numbers[i]>=start&&numbers[i]<=end)
++count;
return count;
}
时间复杂度O(Nlogn) 空间复杂度O(1)
重点在这,对于上面的这个实例,我们可以找到3,但是不能找到2,因为1~2正好有两个,所以这种算法不能找到每一个重复的数字,在我们面试的时候,要考虑好面试官的要求是什么。