数组中数字出现的次数

147 阅读1分钟

题目

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

输入: nums = [4,1,4,6]
输出: [1,6][6,1]

由于计算机的每一个二进制都代表一个数字,那么相同的数字,其二进制是一样,利用异或运算,其两个相同的数字异或为0。那么只有不同数字才不为0。

101 ^ 101 = 000 5^5
101 ^ 001 = 100 5^1

那么对于只有一个不重复数字来说,我们只需要求异或就可以。

那么对于两个来说,我们需要将两个不重复的值分在两组数组里,并且相同的数要在相同的组里。

对于不同数字 那么异或必定会存在1,则就是辨别其不同的地方,我们利用某一位为1,进行区分。

[4,1,4,6]
  4^4^1^6
= 0^1^6
=1^6
= 0001 ^ 0110 = 0111
其中任何一个1,都可以区分
以第一个1 [4,4,6] [1]
以第二个1 [4,4,1] [6]
class Solution {
    public int[] singleNumbers(int[] nums) {
        int n = nums.length;
        int res =0 ;
        for(int i=0;i<n;i++){
            res ^= nums[i];
        }
        int h=1;
        while((h & res) == 0){
            h <<=1;
        }

        List<Integer> l1 = new LinkedList<>();
        List<Integer> l2 = new LinkedList<>(); 

        for(int i=0;i<n;i++){
            if((h&nums[i])!=0){
                l1.add(nums[i]);
            }else{
                l2.add(nums[i]);
            }
        }

        int a = 0;int b=0;
        for(int i=0;i<l1.size();i++){
            a^=l1.get(i);
        }
        for(int i=0;i<l2.size();i++){
            b^=l2.get(i);
        }
        return new int[]{a,b};
    }
}