题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任一一个重复的数字。 例如,如果输入长度为7的数组[2,3,1,0,2,5,3],那么对应的输出是2或者3。存在不合法的输入的话输出-1。
方法1:用set集合
set集合的特点是去重,如果set集合中包含这个元素,返回重复元素,否则把元素填加到set集合中。
class Solution {
public int findRepeatNumber(int[] nums) {
if(nums == null || nums.length == 0) return -1;
Set<Integer> set = new HashSet<>();
for(int i : nums){
if(set.contains(i)){
return i;//如果有返回重复元素
}else{
set.add(i);//否则添加到集合中
}
}
return -1;
}
}
方法2:原地置换
长度为n,数组中数字的范围是0~n-1,相当于如果n = 4,无重复元素排序后下标 0 1 2 3对应的数字也就是 0 1 2 3,我们要做的就是对数组排序,然后让这个数到对应的位置上,可以把它比喻成是“萝卜归位”,1号萝卜要放在一号坑,每个萝卜放在对应的坑上,然后在排序的过程中找有没有重复的元素,
先举例一个没有重复元素情况下的例子
0号坑对应因该是0号萝卜现在他对应的是3号萝卜,不要他现在对应的三号萝卜,他就去和三号坑的萝卜换,换的前提是3号坑上放的也是别人家的萝卜。
但是0号坑还是没找到自己对应的萝卜,他就接着和2号萝卜换。
换完是这样,现在整好是一一对应。
如果有重复元素,萝卜如何找到自己的坑。
0号坑不要1号萝卜和一号坑换
换完1号坑找到了自己的萝卜,0号坑还是没找到自己的萝卜,接着和2号坑换,换完是这样。
0号坑还是没找到,接着和三号坑换,换完是这样。
0号坑不要2号萝卜,想要去和2号坑换,发现2号坑也是2号萝卜,但是这样就没发在换了,说明重复元素出现了。
这种方法就需要多一个坑来交换萝卜。
class Solution {
public int findRepeatNumber(int[] nums) {
if(nums == null || nums.length == 0) return -1;
int temp ;//定义第三个变量用于交换
for(int i = 0; i < nums.length ; i++){
while(nums[i] != i){//交换的时候用while循环,只有0号坑找到了自己对应的才可以进行下一个坑
if(nums[i] == nums[nums[i]]){//无法交换返回重复元素
return nums[i];
}
temp = nums[i];//交换
nums[i] = nums[temp];
nums[temp] = temp;
}
}
return -1;
}
}