这个题目的特点是数组a[n]中所有的数字都在[0,n)内。书上的方法是基于交换的O(n)时间复杂度,但是会改变原数组的内容。 这种解法可以举一个形象的例子:火车上查票。查到某一个座位i时,如果当前坐的这个人的票与座位号不符,那么就让他坐到他应该坐的位置上去。如果他的位置上已经坐的人的票与座位号也相同,那这么个座位的票就是重复出售了的,因为不可能同时有两个人要坐同一个位置。如果这个人的票与座位号不同,也就是说这个人也坐错了位置,那么先让他坐到i,同时继续判断。
public boolean duplicate(int numbers[],int length,int [] duplication) { int temp; if(length<=1) return false; for(int i=0;i<length;i++) { while(numbers[i]!=i) { if(numbers[numbers[i]]!=numbers[i]) { temp=numbers[numbers[i]]; numbers[numbers[i]]=numbers[i]; numbers[i]=temp; } else { duplication[0]=numbers[i]; return true; } } } return false; }下面的这个方法也是O(n)时间复杂度,也会修改原数组,但是它可以找出所有重复的数字,并且可以还原数组。
public static boolean duplicate(int numbers[],int length,List<Integer> duplication) { if(numbers==null||length<=0) return false; for(int i=0;i<length;i++){ if(numbers[i]<0||numbers[i]>length-1) { return false; } } boolean dup=false; for(int i=0;i<length;i++){ int index=numbers[i]; if(index>=length) index -=length; if(numbers[index]>=length) { duplication.add(index); dup=true; } numbers[index] +=length; } //还原数组 for(int i=0;i<length;i++){ numbers[i] %=length; } if(!dup) duplication.add(-1); return dup; }