题目:在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字重复。请找出这个数组中的这个数字,但是不能改变输入的数组。例如,如果输入长度为8的数组{2,3,4,1,0,6,5,2},那么对应的输出的重复数字就是2了。
分析:看到这个,我脑子里第一个想到的就是两个for循环,直接就搞定了!但是这样的话,时间复杂度就会到O(n2)了,肯定不是一个好的办法。第二种就是创建一个辅助的空间,大小为O(n),一个一个填进去,也没有改变前面的数组的顺序;但是这个方法需要的空间有大了。
另外的一种解法是将数组从中间值分为两部分,然后如果左边的个数大于这个中间指,则重复的值在左边,反之在右边;接下来将多的那部分又一分为二,一次类推,最终找到那个值!
代码示例如下:
#include<stdio.h>
int countRange(const int * numbers,int length,int start,int end){
if(numbers == NULL)
return 0;
int i,count = 0;
for(i = 0; i < length; i++){
if(numbers[i] >= start && numbers[i] <= end)
++count;
}
return count;
} //此函数的作用就是统计在某个区间的数字的个数,从而锁定下一个二分之后选择哪个区间
int getDuplication(const int *numbers,int length){
if(numbers == NULL || length <= 0)
return -1;
int start = 1;
int end = length - 1;
while(end >= start){
int middle = ((end - start) >> 1) + start; //此处右移一位相当于除以2
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 main(){
int a[8] = {3,2,5,6,1,7,5,4};
int length = sizeof(a)/sizeof(int);
int i;
for(i = 0; i < length; i++)
printf("%d ",a[i]);
printf("\n");
printf("%d\n",getDuplication(a,8));
for(i = 0; i < length; i++)
printf("%d ",a[i]);
printf("\n");
return 0;
}
public class t2 {
public static int getDuplicate(int[] numbers,int length) {
if(numbers == null || length < 0)
return -1;
int start = 1;
int end = length - 1;
while(start <= end) {
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;
}
public static int countRange(int[] numbers, int length, int start,int end) {
if(numbers == null)
return 0;
int count = 0;
for(int i = 0; i < length; i++) {
if(numbers[i] >= start && numbers[i] <= end)
++count;
}
return count;
}
public static void main(String[] args) {
int[] number = {1,2,3,4,6,7,5,4};
int length = number.length;
System.out.println(getDuplicate(number,length));
return;
}
}