题目:
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
大神的两种解法:(自己用于消化,所以写了这个博客)
原链接:两种解法的链接地址
1)解法一:使用关联容器:哈希表
思路是:
- 创建哈希表unordered_map<int, bool>
- 遍历vector,若哈希表中不存在,就添加到哈希表中,若存在,直接输出。
时间复杂度为O(N),空间复杂度为O(1)
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
unordered_map<int, bool> map;//哈希表
for(int num: nums){ //遍历
if(map[num]) return num; //存在,返回
map[num] = true;
}
return -1;
}
};
2)解法二:原地交换
思路是:
- 元素值与索引是多对一的关系,那么如果让遍历过的元素与索引一一对应(元素放到以元素为索引的位置处),而后遍历的过程中肯定出现重复的元素也想放到此位置。此时就找到了重复的元素。
- 定义遍历索引下标 int i=0; i指向当前未一一对应的元素;
- 遍历数组
- 若i指向的元素与下标是对应的,即nums[i] == i,那么就++i,去判断下一个元素;
- 如果不对应,那么就要交换,将当前元素交换到数组中对应下标的位置,而后继续判断当前的i所指的元素,也就是说i之前的元素都是已经一一对应的。
- 在交换前,要判断当前元素与另一个位置的元素是否相等,若相等,则说明已经存在此元素,则此元素重复。
已经交换过的,或者++i前的都是已经 一一对应的了。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int i=0;
while(i<nums.size()){
if(nums[i]==i){
++i;
continue;//!!!
}
if(nums[i]==nums[nums[i]]){
return nums[i];
}
swap(nums[i], nums[nums[i]]);
}
return -1;
}
};