LeetCode.260 Single Number 3

写作来源

今天在LeetCode上面连续做了Single Number 2和Single Number 3,非常羞耻地说,两题都是看了别人的思路理解以后再写出来的,Single Number 2的解法有人已经在简书上面写了,我这里就解释一些LeetCode上面的Discuss部分的其他人的解法。

思路

首先贴上别人写的代码。

class Solution
{
public:
    vector<int> singleNumber(vector<int>& nums) 
    {
        // Pass 1 : 
        // Get the XOR of the two numbers we need to find
        int diff = accumulate(nums.begin(), nums.end(), 0, bit_xor<int>());
        // Get its last set bit
        diff &= -diff;

        // Pass 2 :
        vector<int> rets = {0, 0}; // this vector stores the two numbers we will return
        for (int num : nums)
        {
            if ((num & diff) == 0) // the bit is not set
            {
                rets[0] ^= num;
            }
            else // the bit is set
            {
                rets[1] ^= num;
            }
        }
        return rets;
    }
};

第一步,如果说写了Single Number的人首先会把所有的数进行异或,最终得到两个不重复两次的数字的异或的结果,这里记为:

diff=b0xorb1 d i f f = b 0 x o r b 1

此时,设所有重复了两次的数字分别为 a0,a1,a2an a 0 , a 1 , a 2 ⋯ a n ,而本题的思想就是通过某一种标识把 b0 b 0 b1 b 1 分离,或者说是把整个输入的列表分成两个部分,这两个部分分别为:
c0,c1cm,b0d0,d1dk,b1{a0,a1,a2an}={c0,c1cm}{d0,d1dk}(523) (523) c 0 , c 1 ⋯ c m , b 0 d 0 , d 1 ⋯ d k , b 1 { a 0 , a 1 , a 2 ⋯ a n } = { c 0 , c 1 ⋯ c m } ∪ { d 0 , d 1 ⋯ d k }

因为集合中没有重复的数字,所以这里为了表示重复数字,加上上标表示重复,即比如 a0 a 0 的两个重复值为 a10 a 0 1 a11 a 1 1 ,所以在上面的两个集合中,存在:
c00xorc10xorc01xorc11xorxorb0=b0d00xord10xord01xord11xorxorb1=b1(524) (524) c 0 0 x o r c 0 1 x o r c 1 0 x o r c 1 1 x o r ⋯ x o r b 0 = b 0 d 0 0 x o r d 0 1 x o r d 1 0 x o r d 1 1 x o r ⋯ x o r b 1 = b 1

由上面的代码可以看出来,这个标识符为 diff d i f f ,原因是,通过 diff=diffxor(diff) d i f f = d i f f x o r ( − d i f f ) 计算以后, diff d i f f 的值只保留了原本的数的最低位,其他的位的值都是0,这算是位运算中最基本的技巧吧。也就是说,原本的 diff d i f f 的最低位也是1,从而推断 b0 b 0 b1 b 1 的相应位肯定分别为 0 0 1,因为只有两个位的值不一样才能够异或出 1 1 。这就说明diff的值是可以作为标识符的。
其实这里我们可以不用管上面所说的 c0,c1cm c 0 , c 1 ⋯ c m d0,d1dk d 0 , d 1 ⋯ d k 分别是多少,反正也会被这个标识符分成两个集合,我们只需要关心能被分成两个集合即可。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值