leetcode [260]Single Number III

Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.

Example:

Input:  [1,2,1,3,2,5]
Output: [3,5]

Note:

  1. The order of the result is not important. So in the above example, [5, 3] is also correct.
  2. Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?

题目大意:

一个数组中,只有两个数字只出现了一次,其他数字都出现了两次,找出这两个数字。

解法:

首先,把数组中的所有数字都异或得到一个结果,这个结果一定是两个只出现了一次的两个数字进行异或得到的结果,那么可以通过这个结果知道这两个数字在哪一位上是不同的,通过这一位将数组分为两个数组,那么这两个数组一定是每一个数组包含一个出现了一次的数字,而且数组剩下的数字都是成对出现的。将这两个数组分别进行异或,那么最后两个数组异或得到的数字就是结果。

java:

class Solution {
    public int[] singleNumber(int[] nums) {
        int[] res=new int[2];
        int s=nums[0];
        for (int i=1;i<nums.length;i++) s^=nums[i];
        int flag=1;
        for(int i=0;i<32;i++){
            if ((s&flag)!=0) break;
            flag<<=1;
        }
        ArrayList<Integer>l1=new ArrayList<>();
        ArrayList<Integer>l2=new ArrayList<>();
        for (int i=0;i<nums.length;i++){
            if ((nums[i]&flag)!=0) l1.add(nums[i]);
            else l2.add(nums[i]);
        }
        s=l1.get(0);
        for (int i=1;i<l1.size();i++)
            s^=l1.get(i);
        res[0]=s;
        s=l2.get(0);
        for (int i=1;i<l2.size();i++)
            s^=l2.get(i);
        res[1]=s;

        return res;
    }
}

  优化过后的java:

  s&=-s可以保留二进制中第一位为1,其余位置都补上0。比如6(二进制110)可以得到2(二进制10)。

class Solution {
    public int[] singleNumber(int[] nums) {
        int[] res=new int[2];
        int s=nums[0];
        for (int i=1;i<nums.length;i++) s^=nums[i];
        s&=-s;
        for (int num:nums){
            if ((num&s)==0) res[0]^=num;
            else res[1]^=num;
        }

        return res;
    }
}

  

posted @ 2019-05-09 21:35  小白兔云  阅读(148)  评论(0编辑  收藏  举报