描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组[2,3,1,0,2,5,3],那么对应的输出是2或者3。存在不合法的输入的话输出-1
数据范围:0≤n≤10000
进阶:时间复杂度O(n) ,空间复杂度O(n)
示例1
输入:[2,3,1,0,2,5,3]
返回值:2
说明:2或3都是对的
public class Solution {
public int duplicate (int[] numbers) {
// return duplicateI(numbers);
return duplicateII(numbers);
}
//方法二:使用HashSet
//时间复杂度O(n),空间复杂度O(n)
private int duplicateII(int[] numbers) {
if (numbers == null || numbers.length == 0) {
return -1;
}
Set<Integer> set = new HashSet<>();
for (int num : numbers) {
if (set.contains(num)) {
return num;
}
set.add(num);
}
return -1;
}
//方法一:位置重排
//既然数组长度为n只包含了0~n-1的数字,那么如果数字没有重复,这些数字排序后将会与其下标一一对应。
//那我们就可以考虑遍历数组,每次检查数字与下标是不是一致的。
//一致的说明它在属于它的位置上,不一致我们就将其交换到该数字作为下标的位置上,如果交换过程中,那个位置已经出现了等于它下标的数字,那肯定就重复了。
//时间复杂度O(n),空间复杂度O(1)
private int duplicateI(int[] numbers) {
if (numbers == null || numbers.length == 0) {
return -1;
}
for (int i = 0; i < numbers.length; i++) {
while (i != numbers[i]) {
if (numbers[i] == numbers[numbers[i]]) {
return numbers[i];
}
int tmp = numbers[numbers[i]];
numbers[numbers[i]] = numbers[i];
numbers[i] = tmp;
}
}
return -1;
}
}