题目:
找出数组中重复的数字。在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1
的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
第一种方法:
解析:
这里利用HashSet(无序,不可重复)的不可重复的特点
当遍历该数组的时候如果不能把下一个数字添加进集合里,说明出现了重复的数字,此时把该数字记录下来,跳出循环,最后返回即可。
注:此算法的时间复杂度是O(n),需要便利一遍数组,空间复杂度是以一个大小为O(n)的哈希表为代价的
class Solution {
public int findRepeatNumber(int[] nums) {
HashSet<Integer> result = new HashSet<Integer>();
int repeatNum=0;
for(int num:nums){
if(!result.add(num)){
repeatNum=num;
break;
}
}
return repeatNum;
}
}
第二种方法:原地置换
解析:该方法利用的是一共n个数,如果没有重复且该数组有顺序的情况下则下标是几,那么对应的数字也应该是几。
思路:
- 循环这个数组
- 接下来判断该数组的下标与该位置的数是否不相等(因为如果相等的话直 接next就行了不需要判断)
- 当不相等时,则需要把当前位置的数字置换到对应的数组下标处
- 交换过后,继续往下走,遇到有与该数字对应的下标处的相同的数字,说明该数字是重复的,直接返回该数字
注:代码中尽管有一个两重循环,但每个数字最多只要交换两次就能找到它自己的位置,因此时间复杂度为O(n)。另外,所有的操作步骤是在输入数组上进行的,不需要额外的分配内存,因此空间复杂度为O(1)。
class Solution {
public int findRepeatNumber(int[] nums) {
int temp;
for(int i=0;i<nums.length;i++){
while(nums[i]!=i){
//查找到比如第四个数字的数与该数字代表的下标处的数相等,则代表重复
if(nums[i]==nums[nums[i]]){
return nums[i];
}
// 置换数字到对应的下标处 使数组变得有序
temp=nums[i];
nums[i]=nums[temp];
nums[temp]=temp;
}
}
return -1;
}
}