题目描述:
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
限制:
2 <= n <= 100000
解题思路:
方法一:
遍历数组元素放到set/map,中判断是否已经有了,有了就返回。时间复杂度O(n)
class Solution {
public int findRepeatNumber(int[] nums) {
Map<Integer,Integer> map =new HashMap<>();
for(int i=0;i<nums.length;i++){
if(!map.containsKey(nums[i])){
map.put(nums[i],1);
}else{
return nums[i];
}
}
return -1;
}
}
HashMap集合中key只能为引用数据类型,不能为基本类型
方法二:
模仿桶排序的方法,新建一个长度为n的数组array,将nums的元素对应到array的下标,对应的值++。判断是否大于1;时间复杂度O(n),额外空间O(n)
class Solution {
public int findRepeatNumber(int[] nums) {
int[] array=new int[nums.length];
for(int i=0;i<nums.length;i++){
if(array[nums[i]]<1){
array[nums[i]]++;
}else{
return nums[i];
}
}
return -1;
}
}
方法三:
原地交换。时间复杂度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进行判断
if(nums[i]==nums[nums[i]]){
return nums[i];
}
temp=nums[i];
nums[i]=nums[temp];
nums[temp]=temp;
}
}
return -1;
}
}
- 注意while这个判断条件
- 注意交换数据的最后一句话 千万不能写成
nums[nums[i]]=temp;
,因为nums[i]
已经在第二句中被修改了