题目描述:在一个长度为n的数组里的所有数字都在0~n-1的范围内,数组中一些数字是重复的,但不知道有几个数字重复,也不知道每个数字重复了几次,请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3.
思路:从下标为0的数开始,将数值与下标值比较。若不等,就将此数与下标等于此数的那个数值交换,直到此数与下标相等,再扫描下一个数,重复之前的比较步骤。
注意:此方法修改原数组的方法
package Function;
//o(n) o(1)
public class duplicate03 {
public boolean duplicate( int numbers[],int length, int[]duplication){
//输入空指针,或者数组长度小于0
if(numbers ==null||length<=0){
return false;
}
//防止长度为n的数组中包含0-n-1之外的数字
for (int i =0;i<length;++i){
if(numbers[i]<0 ||numbers[i]>length-1)
return false;
}
for (int i = 0; i<length;++i){
//索引不等于值
while(numbers[i]!=i){
if(numbers[i]==numbers[numbers[i]]){
duplication[0]=numbers[i];
return true;
}
int temp =numbers[i];
numbers[i]=numbers[temp];
numbers[temp]=temp;
}
}
return false;
}
public static void main(String[] args) {
int [] arr1={};
int [] arr2 = new int[7];
duplicate03 p =new duplicate03();
boolean i =p.duplicate(arr1,0,arr2);
System.out.println(i);
//int [] arr1={};
//boolean i =p.duplicate(arr1,0,arr2);
}
}
若不修改原数组,找到数组中重复的数字代码如下:
package Function;
//不修改数组意味着不交换
//另一个方法就是新创建一个数组,将数值复制到相应的索引值去
//0(nlogn) 0(1)以时间换空间
//二分查找
public class NoalterDuplicate03 {
public int NoalterDuplication(int numbers[],int length){
if(numbers==null||numbers.length<=0){
return -1;
}
for(int i =0;i<length;++i){
if(numbers[i]<0||numbers[i]>length-1)
return -1;
}
//索引值 加减索引0参与无意义
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;
}
public int countRange(int numbers[], int length,int start, int end){
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[]arr1 ={3,2,2,4,8,8,4,5,6};
NoalterDuplicate03 p=new NoalterDuplicate03();
int i=p.NoalterDuplication(arr1,9);
System.out.println(i);
}
}