LeetCode 只出現一次的數字II

hestyle發表於2019-02-23

給定一個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現了三次。找出那個只出現了一次的元素。

說明:
你的演算法應該具有線性時間複雜度。 你可以不使用額外空間來實現嗎?
示例 1:

輸入: [2,2,3,2]
輸出: 3

示例 2:

輸入: [0,1,0,1,0,1,99]
輸出: 99

方法一:利用map將值出現的次數標記,然後找出出現一次的元素。(時間複雜度O(n), 空間複雜度O(n))

class Solution {
public:
	int singleNumber(vector<int>& nums) {
		map<int, int> myMap;
		//遍歷陣列,將值與出現的次數標記
		for (auto num : nums) {
			++myMap[num];
		}
		//遍歷map,尋找出現一次的元素
		for (auto it : myMap) {
			if (it.second == 1) {
				return it.first;
			}
		}
        return 0;
	}
};

在這裡插入圖片描述
方法二:將int數分為32位,那麼按該題的要求,這32位的每一位,所出現過的數目必定是3N或3N+1,3N+1的位級必然是那唯一的一個元素貢獻的。對int數res的每個位進行陣列位與遍歷,出現3N+1的即保留下來,最終刷完32位之後,可得結果。(時間複雜度O(n), 空間複雜度O(1))

class Solution {
public:
	int singleNumber(vector<int>& nums) {
		int count, result = 0, bitN;
		for (int i = 0; i < 32; ++i) {
			count = 0;
			bitN = 1 << i;//右移i位
			for (auto num : nums) {//統計第i位為1的數目
				if (bitN & num) {
					++count;
				}
			}
			if (count % 3 == 1) {
				result |= bitN;
			}
		}
		return result;
	}
};

在這裡插入圖片描述
方法三:使用數字邏輯的計數電路原理,進行標記。參考https://blog.csdn.net/jiangxiewei/article/details/82227451
我們要運用邏輯閘的想法設計一個計數器.計數到3就回歸0.對於每一個二進位制位,出現了多少次1我們可以用兩個二進位制表示(因為這題只需要記錄%3),00表示出現0次,01表示出現1此,10表示出現2次.這樣就記錄了三個狀態,(題目中是出現三次,其實對於x次,我們也可以同理描述).如下(a為高位,b為低位.兩個一起表示一個兩位二進位制表示的數字)
在這裡插入圖片描述
上面是我們計數器需要達成的目標,一個計數迴圈.學過數位電路的同學看到這裡應該就知道怎麼做了.
我們再進一步. 我們遍歷資料,每來一個資料c(這裡一個二進位制)我們的a與b就要開始為c計數,那麼有以下情況
在這裡插入圖片描述
上面比較容易明白,來的是0,那麼我們不統計,原來a,b的統計結果不變
在這裡插入圖片描述
這裡也比較容易明白,當來的是1,那麼只要為其計數增加1就好.
接下來就是我們的重頭戲了.開始設計邏輯閘能讓我們的計數器保持3個狀態記錄迴圈.
我們觀察結果a,可以看到會使結果a=1的狀態僅有 ( a為1 && b為0 && c為0 ) || (a為0 && b為1 && c為1),同理可以推出b的表示式.
故可得出公式結果a結果b的表示式:

結果a = (a & ~b & ~c) + (~a & b & c)
結果b = (~a & ~b & c) + (~a & b & ~c)
另外根據分配率公式也可以變成:
結果b = ~a & (~b & c + b & ~c) = ~a & (b^c) //二進位制進位邏輯 
再然後根據上圖a,c,結果b 三者的關係寫出結果a的邏輯 
結果a = a & ~c & (~結果b) + ~a & c & (~結果b) = (~結果b) & (a^c)

(時間複雜度O(n), 空間複雜度O(1))

class Solution {
public:
	int singleNumber(vector<int>& nums) {
		int a = 0, b = 0;
		for (auto x : nums) {
			a = (a ^ x) & ~b;
			b = (b ^ x) & ~a;
		}
		return a;
	}
};

在這裡插入圖片描述

相關文章