中等-LeetCode 260.只出现一次的数字III

题目

来源:只出现一次的数字III
给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。

示例

在这里插入图片描述

解题思路及代码
1.思路

要通过要找的两个数字对应的某一个不同的二进制位,将数组分为两组,再分别组内异或,即可得到我们要找的两个数。
如果全部进行异或,得到的结果为两个只出现了一次的数的异或结果,并不能知道是哪两个数,但是如果我们能把数组分成两组,两个只出现了一次的数分别放到两组中,这两组数各自进行异或操作,即可分别得到两个只出现了一次的数。
如何将数组进行分组呢?这两个数既然是不同的值,那两数的二进制数的对应位置中,至少有一位是不同的,即一个是1,一个是0,即对应两数异或结果中为1的二进制位。所以我们可以根据异或结果中为1的二进制位来将原数组划分成两个数组。
在代码实现上,我们要在原数组的异或结果的基础上构造一个数,除了我们所选定的那一位为1,其余位均为0,这样该数与数组中每个数相与时,结果为0的可以划分到一组,结果不为0的可以划分另一组。
但是该异或结果不可能正好总是只有一位为0,所以我们可以采取一些方法来实现:

  1. diff &= -diff
  2. diff = (diff & (diff - 1)) ^ diff
  3. diff & 1,不断右移,直到出现1
2. 代码
var singleNumber = function(nums) {
    var xor = 0;
    var a = 0;
    var b = 0;
    for (var i = 0; i < nums.length; i++) {
        xor ^= nums[i];
    }
    diff = xor & (-xor);
    for (var i = 0; i < nums.length; i++) {
        if ((diff & nums[i]) != 0) {
            a ^= nums[i];
        } 
    }
    b = xor ^ a;
    return [a, b];
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值