題目
給定一個範圍在 1 ≤ a[i] ≤ n ( n = 數組大小 ) 的 整型數組,數組中的元素一些出現了兩次,另一些只出現一次。
找到所有在 [1, n] 範圍之間沒有出現在數組中的數字。
您能在不使用額外空間且時間複雜度爲O(n)的情況下完成這個任務嗎? 你可以假定返回的數組不算在額外空間內。
來源:
https://leetcode-cn.com/problems/find-all-numbers-disappeared-in-an-array
示例:
輸入:
[4,3,2,7,8,2,3,1]
輸出:
[5,6]
解答
方法一:
不使用額外空間還要O(n)時間複雜度確實想不到,先解出來再說吧。使用hash
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
std::unordered_set<int> data_set;
std::vector<int> res;
for (auto num : nums) {
data_set.insert(num);
}
for (int i = 1; i <= nums.size(); ++i) {
if (data_set.find(i) == data_set.end()) {
res.push_back(i);
}
}
return res;
}
};
方法二:
這個方法很巧妙,佩服想出這個方法的大神。
- 將數組中的每一個元素的值 減去1 作爲數組下標
- 將對應的下標的值標記爲負值
- 如果不缺數的話那麼數組的數據應該全部變成負值
- 如果某個數缺失了,那麼這個數做下標的數組的值 就沒有變成負值。
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
//把 nums[i] - 1位置的數字標記爲負數
for (int i = 0; i < nums.size(); ++i) {
nums[abs(nums[i]) - 1] = 0 - abs(nums[abs(nums[i]) - 1]);
}
//如果一個數也不缺,那麼全部都爲負值
//如果某個數字缺失了,那麼這個數字做下標對應的數據一定沒有被變成負值
//重複的數字 是重複的下標,
vector<int> res;
for (int i = 0; i < nums.size(); ++i){
if (nums[i] > 0)
res.push_back(i+1);
}
return res;
}
};