分组异或

题目

数组中数字出现的次数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;
    }
}
相关文章
相关标签/搜索