分組異或

題目

數組中數字出現的次數java

題意

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

分析

若是是數值中只有一個這樣的數字,咱們應該怎麼作?數組

根據位運算咱們能夠知道,a ^ a = 0, 0 ^ a = a, a ^ b ^ c = a ^ c ^ b
咱們只要將數組遍歷異或一遍最後的異或值就是這樣的一個數字code

此題目中有兩個這樣的數字a, b,所以咱們按上述操做獲得的結果是這兩個數字的異或值,不是咱們須要的答案
所以咱們須要將數組分爲兩個數組,知足下列的要求it

  1. 相同的數字要分到同一個數組中
  2. a, b要分到不一樣的數組中

只要知足上述的兩個條件,就能分組異或,分別獲得a, b
要將a, b分至不一樣的數組中,就要找到他們的不一樣點加以區分,有上述咱們知道,遍歷異或的到的是a, b的異或值
由異或的計算過程可知,只有在其a, b的二進制位不相等的位置才能二進制位是1,所以咱們只要找到a ^ b的值的二進制位上爲1的位,這樣就知足了條件2
由於相同的數在其對應的二進制位上的值是相同的因此必然會被分到一組,知足條件1io

算法

先對全部數字進行一次異或,獲得兩個出現一次的數字的異或值。class

在異或結果中找到任意爲 1 的位(其餘位爲0),這裏使用不爲0的最低位(利用lowbit作)。遍歷

根據這一位對全部的數字進行分組。二進制

在每一個組內進行異或操做,獲得兩個數字。程序

class Solution {
    public int[] singleNumbers(int[] nums) {
        int[] res = new int[2];
        int ans = 0;
        for(int item : nums) ans ^= item;

        int lowbit = ans & (-ans);

        for(int item : nums){
            if((lowbit & item) == 0)
            res[0] ^= item;
        }

        res[1] = ans ^ res[0];//自反性
        return res;
    }
}
相關文章
相關標籤/搜索