import java.util.HashMap;
import java.util.Map;
/**
* 数组中重复的数字
*
* 在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。
* 请找出数组中第一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
* 返回描述:
如果数组中有重复的数字,函数返回true,否则返回false。
如果数组中有重复的数字,把重复的数字放到参数duplication[0]中。(ps:duplication已经初始化,可以直接赋值使用。)
*/
public class JZ050Duplicate {
/**
* Map
* @param numbers
* @param length
* @param duplication
* @return
*/
public boolean duplicate(int numbers[],int length,int [] duplication) {
if (numbers == null || length <= 1) {
return false;
}
Map<Integer, Integer> map = new HashMap<>();
for (int num : numbers) {
if (!map.containsKey(num)) {
map.put(num, 1);
} else {
duplication[0] = num;
return true;
}
}
return false;
}
/**
* 1、把当前序列当成是一个下标和下标对应值是相同的数组;
* 2、遍历数组,判断当前位的值和下标是否相等:
* 2.1. 若相等,则遍历下一位;
* 2.2. 若不等,则将当前位置i上的元素和a[i]位置上的元素比较:若它们相等,则成功!若不等,则将它们两交换。
* 换完之后a[i]位置上的值和它的下标是对应的,但i位置上的元素和下标并不一定对应;
* 重复2.2的操作,直到当前位置i的值也为i,将i向后移一位,再重复2.
* @param numbers
* @param length
* @param duplication
* @return
*/
public boolean duplicate2(int numbers[],int length,int [] duplication) {
if (numbers == null || length <= 1) {
return false;
}
// 判断数组是否合法(每个数都在0~n-1之间)
for ( int i = 0; i<length; i++ ) {
if (numbers[i] < 0 || numbers[i] > length-1) {
return false;
}
}
int i = 0;
while(i < length){
if(numbers[i] == i){
i++;
}else{
if(numbers[i] == numbers[numbers[i]]){
duplication[0] = numbers[i];
return true;
}else{
int temp = numbers[i];
numbers[i] = numbers[numbers[i]];
numbers[temp] = temp;//别误写为numbers[numbers[i]]=temp;
}
}
}
return false;
}
/*
数组中重复的数字
总结:
1、第一种方法很好理解,可以从一个乱序中找到第一个重复的数字,但是需要开辟新的空间
2、第二种方法不好理解,需要花费很多时间,且第二种方法不能找到第一个重复的数字
*/
}