1. 程式人生 > 其它 >尋找陣列中消失或重複的數字方法歸納

尋找陣列中消失或重複的數字方法歸納

技術標籤:演算法雜湊表

這裡寫目錄標題

前言

在力扣網連續寫了幾道尋找陣列中消失數字以及重複數字的題,發現有一些解法真是過於精妙,那就記錄一波咯~~~~廢話不多說開始吧!

劍指 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;
	}
};

先到這裡,持續更新~~~