[Lc]面试题03数组中重复的数字
Contents
题目
题解
1. 排序法(改变输入数组)
数组排序后找重复项
- 时间复杂度$O(nlog{n})$,主要是排序花费的
- 空间复杂度$O(1)$
class Solution {//三种方法。1.排序
public:
int findRepeatNumber(vector<int>& nums) {
sort(nums.begin(), nums.end());
int res = -1;
for(int i=1; i<nums.size(); ++i){
if(nums[i]==nums[i-1]){
res = nums[i];
break;
}
}
return res;
}
};
2. set法(不改变输入数组)
用set存值,遇到重复的返回
- 时间复杂度$O(n)$,遍历一遍
- 空间复杂度$O(n)$,set存值
class Solution {//三种方法。2.set
public:
int findRepeatNumber(vector<int>& nums) {
unordered_set<int> s;
int res;
for(auto n : nums){
if(s.count(n)) res = n;
s.insert(n);
}
return res;
}
};
3. 挨个数字排序法(改变/不改变输入数组)
若无重复数字,则每个数字nums[i]和下标i相等
- 挨个遍历数组,遇到i,判断nums[i]和i相不相等,若相等,遍历下一个
- 若不相等,判断nums[i]与nums[nums[i]]相不相等,相等找到重复的数字,返回
- 若不相等,交换两个数字,继续对i进行步骤1
- 时间复杂度$O(n)$,遍历一遍
- 空间复杂度
- 不使用额外数组$O(1)$,改变原输入数组
- 使用额外数组$O(n)$,不改变原输入数组
下面代码是改变输入数组的写法,不改变的比较简单,不写了
class Solution {//四个方法。3.挨个移动数字
public:
int findRepeatNumber(vector<int>& nums) {
int res = 0;
int n = nums.size();
for(int i=0; i<n; ++i){
if(i == nums[i]) continue;
if(nums[i] == nums[nums[i]]){
res = nums[i];
break;
}else{
swap(nums[i],nums[nums[i]]);
i--;
}
}
return res;
}
};
4. 二分查找法
若没有重复数字,[0,n/2)的个数就等于n/2
1. 若大于n/2,说明左半边有重复数字,递归
2. 若小于n/2,说明右半边有重复数字,递归
- 时间复杂度$O(n)$,遍历一遍
- 空间复杂度$O(n)$,set存值
书上还写了一个二分查找法,然而我写了半天通过不了,用书上的源码也不行,看别人的题解的二分法也过不去,真是坑。如果有人通过了麻烦贴一下代码,谢谢
Author ChrisHRZ
LastMod 2020-05-09