LeetCode 只出現一次的數字II
給定一個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現了三次。找出那個只出現了一次的元素。
說明:
你的演算法應該具有線性時間複雜度。 你可以不使用額外空間來實現嗎?
示例 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;
}
};
相關文章
- 只出現一次的數字 II
- Leetcode 137:只出現一次的數字 II(最詳細的解法!!!)LeetCode
- LeetCode 只出現一次的數字LeetCode
- LeetCode 只出現一次的數字IIILeetCode
- LeetCode之只出現一次的數字-SwiftLeetCodeSwift
- LeetCode136 只出現一次的數字LeetCode
- leetcode136. 只出現一次數字LeetCode
- leetcode力扣136.只出現一次的數字LeetCode力扣
- LeetCode每日一題:只出現一次的數字(No.136)LeetCode每日一題
- 136只出現一次的數字
- LC-出現一次的數字II
- 136. 只出現一次的數字
- 只出現一次的數字--力扣力扣
- LeetCode 136. 只出現一次的數字【c++/java詳細題解】LeetCodeC++Java
- 找出陣列中只出現一次的數字陣列
- 力扣136.只出現一次的數字力扣
- JZ-040-陣列中只出現一次的數字陣列
- 第一次只出現一次的字元字元
- 在其它數都出現k次的陣列中找到只出現一次的數陣列
- 第一個只出現一次的字元——Java字元Java
- 給定一個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。陣列
- 每日一練(23):第一個只出現一次的字元字元
- JZ-034-第一個只出現一次的字元位置字元
- [演算法練習及思路-leetcode劍指offer(Java解法)]No50.第一個只出現一次的字元演算法LeetCodeJava字元
- LeetCode 299 猜數字遊戲 Java實現LeetCode遊戲Java
- leetcode253——會議室 II——java實現LeetCodeJava
- LeetCode 402 移掉K位數字 HERODING的LeetCode之路LeetCode
- [LeetCode]1207. 獨一無二的出現次數LeetCode
- LeetCode - 1365 - 有多少小於當前數字的數字LeetCode
- (python版)《劍指Offer》JZ34:第一個只出現一次的字元Python字元
- leetcode-90. Subsets IILeetCode
- Leetcode 40 Combination Sum IILeetCode
- Leetcode 213 House Robber IILeetCode
- LeetCode 1103[分糖果II]LeetCode
- 數字中的1——leetcode233LeetCode
- LeetCode:尋找丟失的數字LeetCode
- LeetCode1365有多少小於當前數字的數字LeetCode
- Leetcode508. 出現次數最多的子樹元素和LeetCode