Single NumberIII(leetcode260)

题目

  • 给定一个数组nums,有两个元素只出现了一次,其余的元素都出现了两次,找出只出现了一次的两个元素
  • 举例:输入[1,2,1,3,2,5],输出[3,5]
  • 采用位运算进行

解题思路

  1. 首先根据异或性质,两个相同的数异或为0,0和任意数异或结果为任意数,数组中只有两个数出现1次,其余出现一次
  2. 根据以上性质,我们可以将数组所有值异或得到这两个数的异或结果temp = one ^ two
  3. 此时需要将这两个数分开,此时可以反向考虑,我们异或得到的结果肯定不为0那么这个temp的二进制表示某一位上必然有1的存在
  4. 我们可以根据某一位上1的存在根据这一位将原始数组分为两组,一组这一位上包含这个1,另一组这一位上不包含这个1,如果one和two这两个数在这一位都是1的话,根据异或性质这一位就是0,所以必然可以根据1这位将数组分为两部分
  5. 分组之后的数据再进行数组异或最后就可以得到one和two,因为分组之后一组之中只有一个数据出现1次,其余的数据全部出现两次,根据异或结果最后就是这个出现1次的数据
  6. 举例来说:示例中temp = 3 ^5 = 6,二进制表示是110,此时第二位表示为1,那么我们可以用010这个数据去和数据进行与操作,结果不为0的是一组结果为0的是另一组就可以将3和5分别划分到两组中,然后组内数据相与就可以找到对应的数字

源代码实现

class Solution {
    public int[] singleNumber(int[] nums) {
        int[] result = new int[2];
        int temp = 0;
        //假设这两个数变量分别是one和two,根据异或性质temp = one^two;
        for (int i = 0; i < nums.length; i++) temp ^= nums[i];
        int count = 0;
        //找到第一个不为0的位,count用于计数还原
        while ((temp & 1) == 0) {
            temp >>= 1;
            count++;
        }
        temp = 1;
        //此时根据count将这个数据还原,示例中还原为010形式,移位实现
        while (count != 0) {
            temp <<= 1;
            count--;
        }
        //根据temp进行分类实现结果
        for (int i = 0; i < nums.length; i++) {
            if ((temp & nums[i]) == 0) result[0] ^= nums[i];
            else result[1] ^= nums[i];
        }
        return result;
    }
}

你可能感兴趣的:(Single NumberIII(leetcode260))