给定一个长度为的数组,数组中每一个元素的值都在[1,N]之间,找到1~N中没有出现的数字
其实这个题目是力扣的进阶版要求,本文采用两种 时 间 复 杂 度 O ( n ) , 空 间 O ( 1 ) 的 时间复杂度O(n),空间O(1)的 时间复杂度O(n),空间O(1)的方法
文章目录
利用原数组空间i放到a[i]
- 外循环遍历一遍数组,将i放到a[i]
- 内循环直到遇到a[a[i]] == a[i]为止
- 最后遍历一遍数组i不等于a[i]的放入ans
时间复杂度:
O
(
n
)
空
间
复
杂
度
O
(
1
)
O(n)空间复杂度O(1)
O(n)空间复杂度O(1)
代码:
class Solution {
public:
inline void swap(int &a, int &b){
int temp = a;
a = b;
b = temp;
}
vector<int> findDisappearedNumbers(vector<int>& a) {
vector<int> ans;
for(int i = 0; i < a.size(); i++){
while(a[i] != a[a[i]-1]){
swap(a[i], a[a[i]-1]);
}
}
for(int i = 0; i < a.size(); i++)
if(a[i] != i+1)
ans.push_back(i+1);
return ans;
}
};
注意下标要用a[i]-1
用负数打标记
- 遍历一遍数组,将a[abs(a[i])]打成负数,标记a[i]已经出现过
- 再遍历一遍数组,数组里还是正的元素a[i]说明i没有出现过,放入ans
跑一遍发现比上面交换的方法来得快些
代码:
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& a) {
vector<int> ans;
for(int i = 0; i < a.size(); i++){
if(a[abs(a[i])-1] > 0){
a[abs(a[i])-1] *= -1;
}
}
for(int i = 0; i < a.size(); i++){
if(a[i] > 0)
ans.push_back(i+1);
}
return ans;
}
};
这种方法注意因为每次是取的a[i]作为下标:
- a[i]可能被之前的操作变为负数了,取其为下标的时候需要取绝对值abs(a[i])
- 而且a[i]的范围是[1,n]需要-1
- 故下标用:abs(a[i])-1