面试题3:数组中重复的数字
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
方法1:哈希表
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
vector<int> hashNum(nums.size(), 0); //哈希表存储数字出现的次数;
for(auto x : nums){
if(hashNum[x]) //出现了就返回;
return x;
hashNum[x]++; //没出现就添加进去;
}
return -1;
}
};
时间复杂度:$ O(n) $ ,空间复杂度:$ O(n)$
方法2:原地交换
将每一个数字放回到自己的位置,当扫描到下标为 \(i\) 的数字 \(num[i]\) 时,如果 $num[i]==i $,说明该数字放在了正确的位置上,否则的话看一下它本来应该在的位置 \(num[i]\) ,即 \(num[num[i]]\) 上的数字为多少,二者相等的话说明出现了重复,不相等的话就交换一下。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int len = nums.size();
for(int i = 0; i < len; i++){
while(nums[i] != i){
if(nums[i] == nums[nums[i]])
return nums[i];
else
swap(nums[i],nums[nums[i]]);
}
}
return -1;
}
};
时间复杂度:$ O(n) $ ,空间复杂度:$ O(1)$
拓展题:不修改数组找出重复的数字
在一个长度为n+1的数组 nums 里的所有数字都在 1~n 的范围内。所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字。
不修改数组,不新增数组,使用二分法。该方法不保证找到所有的重复数字,比如:{2,3,5,4,3,2,6,7}。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int left = 1, right = nums.size() - 1;
while(left <= right){
int middle = ((right - left) >> 1) + left;
int count = conutNums(nums, left, middle);
if(left == right){
if(count > 1)
return left;
else
break;
}
if(count > (middle - left + 1))
right = middle;
else
left = middle + 1;
}
return -1;
}
int conutNums(vector<int>& nums, int left, int right){
int count = 0;
for(auto n : nums){
if(n >= left && n <= right)
count++;
}
return count;
}
};

浙公网安备 33010602011771号