260. Single Number III

题目:单个数字3

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.

For example:

Given nums = [1, 2, 1, 3, 2, 5], return [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?

题意:

给定一个整数数组nums,其中除了两个整数只出现了一次,其他所有的整数都出现了两次,找到这两个只出现一次的整数,并返回。

Note:

1、返回集中数字的顺序不重要,怎样都可以;

2、算法应该在线性时间复杂度内,能否使用常数项空间复杂度内实现?


思路一:

很巧妙的利用了Single Number 单独的数字的解法,因为那道解法是可以准确的找出只出现了一次的数字,但前提是其他数字必须出现两次才行。而这题有两个数字都只出现了一次,那么我们如果能想办法把原数组分为两个小数组,不相同的两个数字分别在两个小数组中,这样分别调用Single Number 单独的数字的解法就可以得到答案。那么如何实现呢,首先我们先把原数组全部异或起来,那么我们会得到一个数字,这个数字是两个不相同的数字异或的结果,我们取出其中任意一位为‘1’的位,为了方便起见,我们用 a &= -a 来取出最右端为‘1’的位,然后和原数组中的数字挨个相与,那么我们要求的两个不同的数字就被分到了两个小组中,分别将两个小组中的数字都异或起来,就可以得到最终结果了。

1、在计算机中,负数以其正值的补码形式表达。

2、原码:一个整数,按照绝对值大小转换成的二进制;反码:将二进制数按位取反,所得的新二进制数称为原二进制数的反码;补码:反码加1称为补码。

代码:C++版:20ms

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        //将nums数组中所有数字取异或操作,得到两个不相同数字异或的结果
        int diff = accumulate(nums.begin(), nums.end(), 0, bit_xor<int>()); 
        diff &= -diff;  //获得最右端为1的位,因为是异或结果,所以可以通过该位将两个不相同的数分到不同小组
        vector<int> res(2, 0);
        for (auto &a : nums) {
            if (a & diff)  //利用得到的位将nums数组分成两个小组,采用Single Number的算法实现
                res[0] ^= a;
            else
                res[1] ^= a;
        }
        return res;
    }
};


思路二:

与思路一原理一样,只是使用lowestOneBit进行分组时,只对一个子小组进行了异或操作,而另一个数,则直接采用得到的一个结果与diff相异或得到,这样可以减少轮训nums数组时的异或操作,优化代码速度。

代码:C++版:16ms

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        //将nums数组中所有数字取异或操作,得到两个不相同数字异或的结果
        int diff = accumulate(nums.begin(), nums.end(), 0, bit_xor<int>()); 
        //获得最右端为1的位,因为是异或结果,所以可以通过该位将两个不相同的数分到不同小组
        int lowestOneBit = diff & (~(diff - 1));
        vector<int> res(2, 0);
        for (auto &a : nums) {
            if (a & lowestOneBit)  //利用得到的位将nums数组分成两个小组,采用Single Number的算法实现
                res[0] ^= a;
        }
        res[1] = res[0] ^ diff;
        return res;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值