leetcode每日一道(13)神仙思路!找出只出現一次的數字!(其餘數字都出現兩次、三次)

1. 其餘數字出現兩次——小試牛刀

題目描述
現在有一個整數類型的數組,數組中素只有一個元素只出現一次,其餘的元素都出現兩次。
注意:
你需要給出一個線性時間複雜度的算法,你能在不使用額外內存空間的情況下解決這個問題麼?

Given an array of integers, every element appears twice except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

2. 其餘數字出現三次——神仙解法

題目描述
現在有一個整數類型的數組,數組中只有一個元素只出現一次,其餘元素都出現三次。
注意:
你需要給出一個線性時間複雜度的算法,你能在不使用額外內存空間的情況下解決這個問題麼?

3. 思路

來自牛客的大神的思路,當然這道題爲了速度是必須要用位運算的,這道題本質是什麼呢?
對於題1來說,其實是不難的,假設所有的數據都是成對出現的,那麼所有的數據進行異或之後,一定是歸零的,那麼既然有一個多餘的數字,那麼所有的數字進行異或之後,異或得到的結果就是那個落單的數字!
三個數字重複的就稍微麻煩了,在劍指offer上提供的思路是三個數字各個位上之和肯定是能夠被3整除的,只需要檢驗每個位上的和能否被3整除,能的話,結果在這位上的數字就是0,而不能的話,結果在這位上的數字就是1。那這個思路不僅涉及到位運算,還涉及到四則運算,個人覺得比較混亂。
而在牛客上的大神提出的一個三進制思路令人拍案叫絕。
考慮如下,三進制情況下,我們用變量ones來存儲所有數字加和之後,位爲1的情況;twos用來存儲哪些位數字是2,threes則表示哪些位上加起來已經是3了,這個變量有什麼用呢?threes是由ones和twos得來, 當然是在目前更新的情況下,反向置零ones和twos相應的位,然後threes不用保存。
可能我說得不清楚,沒有大佬理解透徹,我就引用一下大佬的原話:

鏈接:https://www.nowcoder.com/questionTerminal/1097ca585245418ea2efd0e8b4d9eb7a?f=discussion
來源:牛客網
Single Number的本質,就是用一個數記錄每個bit出現的次數,如果一個bit出現兩次就歸0,這種運算採用二進制底下的位操作^是很自然的。Single Number II中,如果能定義三進制底下的某種位操作,也可以達到相同的效果,Single Number II中想要記錄每個bit出現的次數,一個數搞不定就加兩個數,用ones來記錄只出現過一次的bits,用twos來記錄只出現過兩次的bits,ones&twos實際上就記錄了出現過三次的bits,這時候我們來模擬進行出現3次就抵消爲0的操作,抹去ones和twos中都爲1的bits。

舉個例子吧:
ones = 1 0 1 0
twos = 0 1 0 0
這時進來一個新數t=6,它的二進制是 0 1 1 0
想象一下,它進來之後,ones和twos是不是就會變了,這裏要先更新twos,容易得twos第三位(從左到右)會因爲ones和t 變成1,其他位保持,更新爲0 1 1 0,然後ones會更新爲 1 1 0 0 ,threes當然就是ones和twos位都位1的位置被置一,更新爲0 1 0 0,既然threes被更新了,那麼ones和twos對應位就應該被抹去了。ones:1 0 0 0 ,twos:0 0 1 0。然後繼續等待下一個新數 t 。理解到了嗎,這麼清晰,還不懂的話,那你就來打死我。
下面上代碼;

代碼

class Solution {
public:
    int singleNumber(int A[], int n) {
        int ones = 0;
        int twos = 0;
        int threes;
        for (int i=0; i<n;i++){
            int t = A[i];
            twos |= ones&t;
            ones ^= t;
            threes = ones & twos; //默認threes是0;
            ones &= ~threes;
            twos &= ~threes;
        }
        return ones;
    }
};

就是這麼簡潔,舉重若輕,至於其中的先用順序,比如爲什麼要先更新twos,聰明的你,很容易想明白!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章