题目来源
题目描述
题目解析
使用额外空间
遍历一遍数组,在这个过程中,把出现的数字在记录数组中标记一下就可以了,那最后遍历一遍记录数组
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
int n = nums.size();
std::vector<int> vector(n + 1, 0);
for(int num : nums){
vector[num] = -1;
}
std::vector<int> ans;
for(int i = 1; i < vector.size(); i++){
if(vector[i] != -1){
ans.emplace_back(i);
}
}
return ans;
}
};
不使用额外空间
仔细观察一下记录数组,由于我们的数组元素是有范围的,范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ),所以index = nums 1。那能不能只用原数组来做标记呢?可以的。做负号最标记。
在原数组上进行一次遍历,在遍历的过程中,将遇到的元素所对应的index下的元素标记为负。最终哪些index下的元素没有被标记的则说明,这个index对应额元素没有出现过。
这样我们就可以把没有出现过的元素找出来了。可是,把元素标记为负,又因为index = num - 1,那index不就变成负数了吗?这里取绝对值就可以了。每次遍历的时候,我们都取num的绝对值,index = abs(num) - 1,这样index就不会为负数了。这也是为什么要用负号的原因。
vector<int> findDisappearedNumbers(vector<int>& nums) {
for (int i = 0; i < nums.size(); ++i) {
int idx = std::abs(nums[i]) - 1;
nums[idx] = -std::abs(nums[idx]);
}
std::vector<int> vec;
for (int j = 0; j < nums.size(); ++j) {
if(nums[j] > 0){
vec.emplace_back(j + 1);
}
}
return vec;
}
用鸽笼原理。1~n的位置表示1~n
个笼子,如果出现过,相应的“鸽笼”就会被占掉,我们将数字置为负数表示被占掉了。最后再遍历一遍,如果“鸽笼”为正数就是没有出现过的数字