劍指offer刷題 數組中只出現一次的兩個數字

數組中只出現一次的兩個數字

題意
一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。
請寫程序找出這兩個只出現一次的數字。
你可以假設這兩個數字一定存在。
樣例
輸入:[1,2,3,3,4,4]
輸出:[1,2]
思路 一看到這種數組中只出現幾次的數字就要想到用位運算的性質進行解答
解題步驟
1、先找到x和y異或的和
2.找異或和的第k位是1,根據第k位是1還是0將集合進行分開最後得到的一個集合是x另一個結合是y;

class Solution {
public:
    vector<int> findNumsAppearOnce(vector<int>& nums) {
        vector<int> res;
        if(nums.empty()) return res;
        int sum=0;
        for(auto x:nums) sum^=x;
        int y=0;
        int k=0;
        while(!(sum>>k&1)) k++;
        for(auto x:nums)
        {
            if(x>>k&1)
            y^=x;
        }
        /*res.push_back(y);
        res.push_back(sum^y);
        return res;*/ 
        return vector<int> {y,sum^y}; //數組返回的小技巧
    }
};

數組中唯一隻出現一次的數字

在一個數組中除了一個數字只出現一次之外,其他數字都出現了三次。
請找出那個只出現一次的數字。
你可以假設滿足條件的數字一定存在。

樣例

輸入:[1,1,1,2,2,2,3,4,4,4]
輸出:3
這道題目可以用狀態機做到時間複雜度爲o(n)和額外的空間爲o(1)
第一種思路 遍歷統計數組中的每個數字,統計每一位出現1的次數,然後每一位mod3等於0說明這個數出現了三次,所以最後的結果就是出現了1次的數字。
時間複雜度o(32n) 空間複雜度o(32)

class Solution {
public:
    int findNumberAppearingOnce(vector<int>& nums) {
        int n=nums.size();
        int bit[32]={0};
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<32;j++)
            {
                if((nums[i]>>j)&1)
                {
                    bit[j]++;
                }
            }
        }
        int res=0;
        for(int i=0;i<32;i++)
        {
            if(bit[i]%3)
            {
                res+=1<<i;
            }
        }
        return res;
        
    }
};

用狀態機做到時間複雜度爲o(n)和額外的空間爲o(1)

class Solution {
public:
    int findNumberAppearingOnce(vector<int>& nums) {
        int ones = 0, twos = 0;
        for (auto x : nums)
        {
            ones = (ones ^ x) & ~twos;
            twos = (twos ^ x) & ~ones;
        }
        return ones;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章