Single Number II -- 找出數組中唯一出現一次的數,其它數都出現了三次



原題:

Given an array of integers, every element appears three times except for one. Find that single one.

=>給定一個數組,除了一個元素,其它每個元素都出現了三次,找出這個出現一次的元素

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

注意:

=>你的算法需要一個線性的複雜度,能否不適用額外的空間來實現這個功能。

class Solution {
public:
    int singleNumber(int A[], int n) {

    }
};


曉東分析:

    其實在之前的博客中,我們曾今分析過其它元素都出現了兩次,然後找出只出現一次的方法,見《Single Number--找出數組中唯一的一個只出現一次的元素》,當時使用的是一直異或來解決的。看到這個的問題的時候,我們不禁會想,是否也有同樣的方法來解決呢,什麼情況下三個相同的數字才能消除呢,這樣的想法很不幸,基本就走入了死衚衕。所以有時我們需要換一個角度來思考問題,我們仍然從位運算來考慮。一個數從二進制的角度來看,無非就是0和1,若是我們只從各個位來看,就把這一位的內容加起來,除以3,剩餘的餘數應該就是單獨剩下的這個數在這一位上的值。有了單獨這個數在各個位的值,這一個剩下的數也就出來了。這樣來看,我們需要一個大小爲32的數組來保存這個數,這個空間並不會隨着數組n值的增加而變化,所以從空間角度來看是沒有問題的。


代碼實現:

class Solution {
public:
    int singleNumber(int A[], int n) {
        int bit_time[32] = {0};
        int i = 0;
        int j = 0;
        int result = 0;
        for(i = 0; i < 32; i++){
            for(j = 0; j < n; j++){
                bit_time[i] += (A[j] >> i) & 0x01;
            }
            result |=  (bit_time[i] % 3) << i;
        }
        return result;       
    }
};

運行結果:

11 / 11 test cases passed.
Status:

Accepted

Runtime: 80 ms


曉東分析二:

    看了上面的分析之後,我們突然會想是否有一些更簡潔的方法來實現這個問題。同樣從位運算的角度來看,我希望一個數用來表示出現一次的位,也就是說這個數的爲1的位就表示這個位上面的數出現過了一次,比如0x10001,就表示bit[0]和bit[4]就是出現過了一次的位。然後再用一個數表示出現過了兩次的位,再用一個數表示出現過了3次的位。只要這個位出現過了3次,我就把這個位拿清除掉,這樣剩餘的最後出現過一次的位的這個數就是我們要找的數了。


代碼實現二:

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


運行結果二:

11 / 11 test cases passed.
Status:

Accepted

Runtime: 24 ms


從兩次的運行結果來看,顯然第二次的運行速度24ms要優於第一次的80ms。


希望大家有更好的算法能夠提出來,不甚感謝。


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