题目描述
不修改数组找出重复的数字。在一个长度为n+1的数组中的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的。在不修改输入数组的情况下找出数组中任意一个重复数字。例如输入长度为8的数组{2, 3, 5, 4, 3, 2, 6, 7},则对应输出的是2或者3。
解析
本题目有三种策略,一种利用哈希表、一种是利用下标的位置交换元素,这两种策略与【数组中重复的数字】一样。这里说例外一种。
策略
利用分治法,将n分为两个区间[1,n/2],(n/2+1,n],遍历数组中元素分别落在[1,n/2],(n/2+1,n]区间的个数,假如落在[1,n/2]的个数大于n/2,则继续将[1,n/2]分为两个区间,直到最后分为两个单区间,查找数组落在两个单区间个数是否大于1,若大于1,该区间的值就是重复数字。
代码
public class Main {
public static void main(String []args)
{
int[] arr=new int[]{2,5,1,5,3,4};
int[] duplication=new int[1];
System.out.println(duplicate(arr,arr.length,duplication));
System.out.println(duplication[0]);
}
public static boolean duplicate(int numbers[],int length,int [] duplication)
{
int result=divDup(numbers,1,length-1);
if(result==-1)
{
return false;
}
else
{
duplication[0]=result;
return true;
}
}
public static int divDup(int numbers[],int start,int end)
{
int mid=(start+end)/2;
int before=0;
int last=0;
if(start==end)
{
return start;
}
for(int i=0;i<numbers.length;i++)
{
if(start<=numbers[i]&&numbers[i]<=mid)
{
before++;
}
else if(mid<numbers[i]&&numbers[i]<=end){
last++;
}
}
if(before>mid-start+1)
{
return divDup(numbers,start,mid);
}
else if(last>end-mid)
{
return divDup(numbers,mid+1,end);
}
else
{
return -1;
}
}
}