題意:給你一個vector數組,只有一個數出現一次,其余的數都出現三次,返回那個出現一次的數。要求:時間復雜度O(N),空間復雜度O(1)。
背景知識:
異或操作規(guī)則:相同位相同元素異或后為0,相同位不同元素異或后為1.異或操作是一種疊加狀態(tài),當把元素val異或一個元素倉庫set的時候,如果set中不存在val元素,那么set = A ^ 0 = A,相當于把A元素疊加到了set上;如果set中已經存在val元素,那么set = A ^ A = 0,相當于把A元素從set中移除了。
與操作規(guī)則:相同位全為1時與操作結果為1,其他情況結果為0.與操作是一種留存操作,即當且僅當執(zhí)行與操作的兩個元素對應位置都是1時結果才為1.
非操作規(guī)則:針對某一特定位置,1變0,0遍1.非操作是一種反轉操作,A & (!A)= 0,相當于將A從set中刪除。
解題思路:
使用兩個集合set1,和set2,分別使用異或狀態(tài)疊加到集合上,元素A第一次出現則將A疊加到set1上,第二次出現則把A從set1中刪除并疊加到set2上,第三次出現則從set2中刪除。
對集合中所有元素都執(zhí)行上述操作,最后set2為空集,set1僅留下出現了一次的元素。
Here is some intuition to help understand this nice and concise solution:
First of all, consider the (set^val) as one of the following:
- adding "val" to the "set" if "val" is not in the "set" => A^0 = A
- removing "val" from the "set" if "val" is already in the "set" => A^A = 0
Assume "ones" and "twos" to be sets that are keeping track of which numbers have appeared once and twice respectively;
"(ones ^ A[i]) & ~twos" basically means perform the above mentioned operation if and only if A[i] is not present in the set "twos". So to write it in layman:
IF the set "ones" does not have A[i]
Add A[i] to the set "ones" if and only if its not there in set "twos"
ELSE
Remove it from the set "ones"
So, effectively anything that appears for the first time will be in the set. Anything that appears a second time will be removed. We'll see what happens when an element appears a third time (thats handled by the set "twos").
After this, we immediately update set "twos" as well with similar logic:
"(twos^ A[i]) & ~ones" basically means:
IF the set "twos" does not have A[i]
Add A[i] to the set "twos" if and only if its not there in set "ones"
ELSE
Remove it from the set "twos"
So, effectively, any number that appears a first time will be in set "ones" so it will not be added to "twos". Any number appearing a second time would have been removed from set "ones" in the previous step and will now be added to set "twos". Lastly, any number appearing a third time will simply be removed from the set "twos" and will no longer exist in either set.
Finally, once we are done iterating over the entire list, set "twos" would be empty and set "ones" will contain the only number that appears once.
class Solution {
public:
int singleNumber(vector<int>& nums) {
int first = 0, second = 0;
for(int i = 0; i < nums.size(); i++){
first = (first ^ nums[i]) & (~second);
second = (second ^ nums[i]) & (~first);
}
return first;
}
};