LeetCode:剑指Offer 03. 数组中重复的数字
文章目录
原题LeetCode链接:剑指Offer 03. 数组中重复的数字
题目:找出数组中重复的数字
在一个长度为 n 的数组 nums
里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2或3
限制:2 ≤ n ≤ 100000
方法一:排序
思路:数组元素是数字,对其进行排序,若有重复则在排序后数组的相邻位置,遍历数组即可找到。排序时间复杂度O(nlogn)
,空间复杂度O(1)
。C++代码如下:
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
sort(nums.begin(), nums.end());
int length = nums.size();
for(int i = 0; i < length-1; i++){
if(nums[i] == nums[i+1]){
return nums[i];
}
}
return -1;
}
};
tips: sort()
用法:
头文件:#include<algorithm>
void sort (RandomAccessIterator first, RandomAccessIterator last);
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
first
:待排序数组起始位置;
last
:待排序数组末尾位置,要排序的最后一个元素的后一个元素位置,[first,last);
comp
:排序的方法,可以是升序也可以是降序,不写则默认升序。
方法二:集合法、unordered_set
思路:首先构建一个空集合,然后遍历数组,如果元素不在集合中则将其插入集合中;若元素在集合中,则说明有重复。
tips :set
内部使用红黑树实现,具有自动排序的功能,因此内部元素在任何时候都是有序的;unordered_set
基于哈希表,数据插入和查找时间复杂度低,代价是消耗较多内存,不能自动排序。本题只需要插入与查找,因此选用unordered_set
时间上的差别可自行尝试使用两种结构进行提交。空间复杂度O(n)
,时间复杂度为O(n)
。C++代码如下:
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
unordered_set<int> s;
int length = nums.size();
for(int i = 0; i < length; i++){
if(s.find(nums[i]) == s.end()){
s.insert(nums[i]);
}
else{
return nums[i];
}
}
return -1;
}
};
方法三:就地交换
思路:因为数组中的数字都是在0~n-1
范围内的,如果没有重复的元素那么数据值和下标应该是相等的。而如果有重复的值的话,有些位置放的就不是对应的值,那么我们可以尝试将它放回对应的位置。
1)如果对应的位置有一个符合的元素,就说明该数字重复了;
2)如果对应的位置也不是符合的元素,那么就将两者交换,将上一个元素和正确位置配对,继续寻找新的元素的位置。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int length = nums.size();
for(int i = 0; i < length; i++){
if(i == nums[i]){//如果元素和位置对应,则继续
continue;
}
else{//否则
while(i != nums[i]){//循环,直到元素与位置对应
if(nums[nums[i]] == nums[i]){//此元素对应的位置上已经有一个符合的了
return nums[i];//说明已经重复,返回元素即可
}
else{//元素对应位置上也是不符合的元素,那么就和此元素交换使它符合,然后继续寻找新位置
int temp = nums[nums[i]];
nums[nums[i]] = nums[i];
nums[i] = temp;
}
}
}
}
return -1;
}
};
如果有错误之处,还望指出!