题目:在一个长度为n的数组里所有的数字都是在0到n-1范围,数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次,请找出数组中任意一个重复的数字,eg,输入长度为7的数组a={2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3
分析:可考虑几种方法
1.先把输入的数组排序,从排序的数组中找出重复的数字,即从头到尾扫描排序后的数组,排序长为n的数组的时间复杂度为O(nlogn)
2.哈希表,从头到尾顺序扫描数组的每个数,每扫描到一个数字的时候,都可以用O(1)的时间判断哈希表里是否已经包含了该数字,如果哈希表里还没有该数字,就把它加入哈希表,如果有则找到一个重复数字,时间复杂度为O(n),但是以O(n)的空间作为代价
3.从头到尾扫描数组中的数字,当扫描到下标为i的数字时,首先比较这个数字(m)是否等于i,如果是,接着扫描下一个数字,如果不是,再拿它和第m个数字进行比较,如果它和第m个数字相等,就找到了一个重复的数字(该数字在下标为i和m的位置都出现了),如果它和第m个数字不相等,就把第i个数字和第m个数字交换,把m放到属于它的位置,接着重复比较、交换过程。时间复杂度为O(n),空间为O(1)
import java.util.*;
public class wr51duplicate {
public static int duplicate(int numbers[],int length){
if(numbers==null || numbers.length==0){
return -1;
}
Arrays.sort(numbers);
int flag=0;
int duplication=0;
for(int i=0;i<length-1;i++){
if(numbers[i]==numbers[i+1]){
duplication=numbers[i];
flag=1;
break;
}
}
return duplication;
}
public static int duplicate2(int numbers[],int length){
if(numbers==null || numbers.length==0){
return -1;
}
HashSet<Integer> hs=new HashSet<>();
int duplication=0;
for(int i=0;i<length;i++){
if(!hs.add(numbers[i])){
duplication=numbers[i];
break;
}
}
return duplication;
}
public static boolean duplicate(int numbers[],int length,int [] duplication){
if(numbers==null || numbers.length==0){
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) {
// TODO Auto-generated method stub
int []a={2,3,1,0,2,5,3};
int []result=new int[1];
System.out.println(duplicate(a,a.length));
System.out.println(duplicate2(a,a.length));
System.out.println(duplicate(a,a.length,result));
}
}