在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
| 暴力法
class Solution {
public int findRepeatNumber(int[] nums) {
for(int i = 0; i < nums.length; i++) {
for(int j = i+1; j < nums.length; j++) {
if(nums[i] == nums[j]) {
return nums[i];
}
}
}
return -1;
}
}
时间复杂度:O(N^2)
空间复杂度:O(1)
| 哈希法 空间换时间
class Solution {
public int findRepeatNumber(int[] nums) {
Set<Integer> set = new HashSet<>();
// the repeated number
int repeat = -1;
for(int num : nums) {
if(!set.add(num)) {
repeat = num;
break;
}
}
return repeat;
}
}
时间复杂度:O(N)
空间复杂度:O(N)
| 排序法
class Solution {
public int findRepeatNumber(int[] nums) {
Arrays.sort(nums);
for(int i = 0; i < nums.length; i++) {
if(nums[i] == nums[i+1]) {
return nums[i];
}
}
return -1;
}
}
时间复杂度:O(NlogN)
空间复杂度:O(1)
| 原地置换法
思路:利用数据特性(所有数字都在0~n-1的范围内)和数组索引,求出重复地元素。
- 遍历数组 nums ,设索引初始值为 i = 0:
- 若 nums[i] == i : 说明此数字已在对应索引位置,无需交换,因此执行 i += 1 与 continue ;
- 若 nums[nums[i]] == nums[i] : 说明索引 nums[i] 处的元素值也为 nums[i],即找到一组相同值,返回此值 nums[i];
- 否则: 当前数字是第一次遇到,因此交换索引为 i 和 nums[i] 的元素值,将此数字交换至对应索引位置。
- 若遍历完毕尚未返回,则返回 -1−1 ,代表数组中无相同值。
class Solution {
public int findRepeatNumber(int[] nums) {
for(int i = 0; i < nums.length; i++) {
// set i to correct index
while(nums[i] != i) {
// need to swap
if(nums[i] == nums[nums[i]]) {
return nums[i];
}
// swap nums[i] -> nums[nums[i]]
int temp = nums[i];
nums[i] = nums[temp];
nums[temp] = temp;
}
}
return -1;
}
}
时间复杂度:O(N) (遍历数组使用 O(N) ,每轮遍历的判断和交换操作使用 O(1))
空间复杂度:O(1)