题目一:
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3。
思路一:
利用哈希表解决问题。从头到尾扫描数组的每个数字,每扫描到一个数字,用O(1)的时间来判断哈希表是否包含了该数字。如果哈希表里还没有该数字,就加入哈希表,否则就找到了一个重复数字;
public static void main(String[] args) {
int[] array = new int[] {2,3,1,0,2,5,3};
Set<Integer> aset = new HashSet<>();
for (int i = 0; i <array.length ; i++) {
boolean isnew = aset.add(array[i]);
if (!isnew) System.out.println(array[i]);
}
}
思路二:
由于数组有重复数字,将数组排序之后有的位置可能存在多个数字,有的位置可能没有数字。我们从头到尾扫描数组中的数字。当扫描到下表为i的数字时,首先比较这个数字(用m表示)是不是等于i。如果是,则扫描下一个数字;如果不是,则拿他和第m个数字比较。如果他和第m个数字相等,则找到重复数字,如果不相等,则将两数字交换。接下来重复比较,交换的过程,直到我们发现一个重复数字。
public static void main(String[] args) {
int[] array = new int[] {2,3,1,0,2,5,3};
for (int i = 0; i <array.length ; i++) {
if (array[i]!=i) {
if(array[array[i]]==array[i]){
System.out.println(array[i]);
}
else
{
int tmp = array[i];
array[i] = array[array[i]];
array[tmp]=tmp;
}
}
}
}
题目2:
在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个是重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组。例如,如果输入长度为8的数组{2,3,5,4,3,2,6,7},那么对应的输出是重复的数字2或者3。
思路:
类似2分法的思路。由于N+1个数组分布在1~N的范围内,我们找出中间数字M,将1到N分为1到M,M+1到N。若前者统计属于前者的数字个数,若大于M,则继续对1到M进行划分,否则对后者进行划分。当数组大小小于等于2时,循环结束。
public static void getNum(int[] array,int start,int midddle,int end){
int count=0;
for (int i = 0; i <array.length ; i++) {
if (array[i]<=midddle&&array[i]>=start){
count++;
}
}
if (end-start>1) {
if (count <= midddle - start) getNum(array, midddle+1, (midddle + end) / 2, end);
else getNum(array, start, (midddle + start) / 2, midddle);
}
else {
//System.out.println(start+""+midddle+""+end);
//System.out.println("count: "+count);
if (count <= 1) System.out.println(end);
else System.out.println(start);
}
}
}