题目
在一个长度为n的数组里的所有数字都在0到n-1的范围内。数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
解法一:最好的解法
首先要明确一个事,数组长度为n,数组下标为0到n-1。
若数组中没有重复数字,将数组排序,数组中存储的值将与其下标值一一对应相等。当数组中有重复数字的时候,此时将数组排序,必将有一个现象:最少存在一个重复的值不但在其对应的下标处,还存在于别处。
从头到尾扫描数组,临时变量m存储待比较的数。若m==i,继续往后扫描,若m!=i,将其与numbers[m]处的值相比较,若相等,说明m是重复的数,返回true并将其赋值给duplication[0],若不相等,将二者交换,然后继续扫描。
public boolean duplicate1(int[] numbers, int length, int[] duplication) {
for (int i = 0; i < length; i++) {
int m = numbers[i];
if (m != i) {
if (m == numbers[m]) {
duplication[0] = m;
return true;
} else { // 交换
numbers[i] = numbers[m];
numbers[m] = m;
}
}
}
return false;
}
解法二:哈希表
建立一个flags数组,长度为length,初始化值全为0。
扫描numbers数组,若flags对应位置值为0,将该处标志位值置1,这样当下次又对应到该处时,若flags对应位置为1,说明该位置已经存在数,为重复。
public boolean duplicate2(int[] numbers, int length, int[] duplication) {
int[] flags = new int[length];
for (int i = 0; i < length; i++) {
if(flags[numbers[i]] == 1) {
duplication[0] = numbers[i];
return true;
}else {
flags[numbers[i]]=1;
}
}
return false;
}
解法一:我第一遍做的方法
第一重循环,i 扫描数组 numbers
第二重循环,j 初始值设为 i + 1,即 j 从 i 后的一个位置开始往后遍历并分别与 numbers[i] 进行比较,一旦有相等,下标 i 的位置为第一个重复数字,将其赋值给 duplication[0] 并返回 true
public boolean duplicate(int[] numbers, int length, int[] duplication) {
for (int i = 0; i < length; i++) {
for (int j = i + 1; j < length; j++) {
if (numbers[j] == numbers[i]) {
duplication[0] = numbers[i];
return true;
}
}
}
return false;
}