LeetCode 4月28每日一題 面試題56 - I. 數組中數字出現的次數 LeetCode

問題描述:

一個整型數組 nums 裏除兩個數字之外,其他數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。要求時間複雜度是O(n),空間複雜度是O(1)。

示例 1:

輸入:nums = [4,1,4,6]
輸出:[1,6] 或 [6,1]
示例 2:

輸入:nums = [1,2,10,4,1,4,3,3]
輸出:[2,10] 或 [10,2]

解題思路:

若不考慮時間空間複雜度,建立map鍵值對,統計字符個數,如下:

class Solution {
public:
    vector<int> singleNumbers(vector<int>& nums) {
        map<int,int> m;
        //統計個數
        for(int i=0;i<nums.size();i++){
            m[nums[i]]++;
        }
        vector<int> res;
        //遍歷查找
        map<int, int>::iterator iter;
        for(iter = m.begin(); iter != m.end(); iter++) {
            if(iter->second==1) res.push_back(iter->first);
        }
        return res;
    }
};

可是題目要求,時間複雜度O(n),空間複雜度O(1)

於是上面的思路不行,轉換思路,這題其實我最開始寫的時候只有一半思路

就是使用^運算符,異或運算符,是相同取0,不同取1

例如

A = 0011 1100

B = 0000 1101

A^B = 0011 0001

同時還有與&,或|運算符

A&B = 0000 1100

A|B = 0011 1101

假設問題1:

如果數組中只存在一個單獨出現一次的元素,其他元素都出現倆次,nums={a,a1,a1,...,an,an},類似這種形式,求出現一次的元素值

數組中的全部元素進行異或運算

res = a^a1^a1^...^an^an 

已知ai^ai=0 則res = a即爲出現一次的元素

此問題就是LeetCode 136題,感興趣的可以看看LeetCode 136

但是題意已給出數組中,只有倆個數字出現一次,其餘都出現了倆次,nums={a,a1,a1,b,...,an,an}就是這種形式

首先將數組中的全部元素進行異或運算

res = a^a1^a1^b^...^an^an

已知ai^ai=0,則res=a^b,則我們已經求出res爲倆個單獨元素的異或值

當時做到這裏,我就卡殼了,後來看了大神的解法

既然a,b 不一樣,那麼res肯定不是0,那麼res的二進制肯定至少有1位(第n位)是1,只有0^1纔等於1

所以a,b 在第n位,要麼a是0,b是1 ,要麼b是0,a是1

A = 0011 1100

B = 0000 1101

A^B = 0011 0001  如此例子,B在第一位是1,A在第一位是0。

在計算機中 數字都是以補碼形式存在,正數補碼等於自己,負數的補碼等於反碼+1,反碼是符號位不變,其他位取反

s = 3 ^ 5; 0011 ^ 0101 = 0110 = 6假設int是8位

-6  原碼1000 0110

反碼1111 1001

補碼1111 1010

下面的建議大家牢記,除非你對計算機基礎掌握很熟練

s&(-s) = 0000 0010

令k = s&(-s),則k就是就是保留s的最後一個1(從右往左),並且將其他位變爲0  也就是s最後一個1是倒數第二位

k&3 = 0010,k&5=0000

此時我們就可以用k來區分倆個單獨數字,這個時候我們考慮數組裏面其他成對出現的元素,

值分爲倆類,k&a=0 或者 k&a!=0

到這裏大家就發現了,使用k將此問題分解爲倆個上面所描述的問題1,具體代碼如下:

class Solution {
public:
    vector<int> singleNumbers(vector<int>& nums) {
        int ans = 0;
        for(int i=0;i<nums.size();i++){
            ans = ans^nums[i];
        }
        int k = (-ans)&ans;
        vector<int> res(2,0);
        for(int i=0;i<nums.size();i++){
            if(k&nums[i]){
                res[0]=res[0]^nums[i];
            }else{
                res[1]=res[1]^nums[i];
            }
        }
        return res;
        
    }
};

 

 

 

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