leetcode[137] Single Number II


題目和上題類似,這里給的數組僅有一個數出現一次,其他的出現3次。返回那個出現一次的數。

這題還是比較難想到的。不想上一題只要異或一下就可以了,不用額外操作。

法一:還是用map方法

class Solution {
public:
int singleNumber(int A[], int n)
{
    unordered_map<int , int> umap;
    for (int i = 0; i < n; i++)
    {
        umap[A[i]]++;
    }
    for (int i = 0; i < n; i++)
    {
        if (umap[A[i]] == 1)
            return A[i];
    }
}
};

法二:還是利用位運算才有辦法實現不用額外空間,就是遍歷32次每次記錄某位的出現的次數,如果不能被三整除,說明那個出現一次的就在該位有值,那么ans 或該位一下就可以了。

int singleNumber(int A[], int n)
{
    int ans = 0;
    for (int i = 0; i < 32; i++)
    {
        int cnt = 0, bit = 1 << i;
        for (int j = 0; j < n; j++)
        {
            if (A[j] & bit) cnt++;
        }
        if (cnt % 3 != 0)
            ans |= bit;
    }
    return ans;
}

法三:還是位運算,這里利用二進制模擬a進制的方法。對於此題,a為3.

這里分析和拓展的很好:

對於除出現一次之外的所有的整數,其二進制表示中每一位1出現的次數是3的整數倍,將所有這些1清零,剩下的就是最終的數。用ones記錄到當前計算的變量為止,二進制1出現“1次”(mod 3 之后的 1)的數位。用twos記錄到當前計算的變量為止,二進制1出現“2次”(mod 3 之后的 2)的數位。當ones和twos中的某一位同時為1時表示二進制1出現3次,此時需要清零。即用二進制模擬三進制計算。最終ones記錄的是最終結果。

int singleNumber(int A[], int n) {
    int ones = 0, twos = 0, xthrees = 0;
    for(int i = 0; i < n; ++i) {
        twos |= (ones & A[i]);
        ones ^= A[i];
        xthrees = ~(ones & twos);
        ones &= xthrees;
        twos &= xthrees;
    }

    return ones;
}

該文的拓展很值得學習!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM