尋找陣列中消失或重複的數字方法歸納
阿新 • • 發佈:2021-02-14
這裡寫目錄標題
前言
在力扣網連續寫了幾道尋找陣列中消失數字以及重複數字的題,發現有一些解法真是過於精妙,那就記錄一波咯~~~~廢話不多說開始吧!
劍指 Offer 03. 陣列中重複的數字
找出陣列中重複的數字。
在一個長度為 n 的陣列 nums 裡的所有數字都在 0~n-1 的範圍內。陣列中某些數字是重複的,但不知道有幾個數字重複了,也不知道每個數字重複了幾次。請找出陣列中任意一個重複的數字。
力扣原題傳送門
1、雜湊表法
使用雜湊表記錄出現過的數字,一邊遍歷陣列一邊查詢此數是否存在於雜湊表中
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
unordered_set<int> historyNums;
for(auto& p:nums){
if(!historyNums.count(p))
historyNums.insert(p);
else return p;
}
return -1;
}
};
一次遍歷,時間複雜度O(N),使用雜湊額外空間,空間複雜度O(N);
2、標記法
巧妙之處在於 nums 裡的所有數字都在 0~n-1 的範圍內 ,剛好對應的是長度為n的陣列下標,我們如果將陣列中的元素當做下標使用,將這個數加上一個長度 n ,如果遍歷過程發現一個數已經大於n - 1,說明該數之前被標記過,所以下標對應值就是我們需要尋找的重複數字。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int len=nums.size();
for(auto & p:nums){
int index=p % len;
if(nums[index]>=len)
return index;
nums[index] += len;
}
return -1;
}
};
一次遍歷,時間複雜度O(N),使用了常數空間,空間複雜度O(1);
448. 找到所有陣列中消失的數字
給定一個範圍在 1 ≤ a[i] ≤ n ( n = 陣列大小 ) 的 整型陣列,陣列中的元素一些出現了兩次,另一些只出現一次。
找到所有在 [1, n] 範圍之間沒有出現在陣列中的數字。
您能在不使用額外空間且時間複雜度為O(n)的情況下完成這個任務嗎? 你可以假定返回的陣列不算在額外空間內。
原題傳送
標記法
是不是似曾相識的感覺,沒錯,陣列中的元素數值在 1~n 之間,與陣列下標 0~n -1 相差為1,因此我們依然可以將這些元素減一的值當做下標使用進行標記,標記完我們再次遍歷陣列,若發現大於 0 的數,說明此數未被標記,那麼它所對應的下標值加一的這個數肯定不在陣列中(說得比較亂,可能程式碼比較好理解一些)
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
int n = nums.size();
for (int i = 0; i < n; i++) {//遍歷陣列進行標記
int index = abs(nums[i]) - 1;//下標需要取絕對值,因為有些元素被標記成了負數
if (nums[index] > 0)//已經被標記過一次的數就不需要再次標記
nums[index] = 0 - nums[index];
}
vector<int> res;
for (int i = 0; i < n; i++)
if (nums[i] > 0)
res.push_back(i + 1);
return res;
}
};
先到這裡,持續更新~~~