206.只出现一次的数字|||(位运算)

题目描述与解析:

 

这道题对我来说很难,根本就没有思路。所以我就仔细看了大佬发的题解,害怕以后忘记就写了这一篇博客,算是做的笔记吧。

位运算

     例子: nums = [ 1, 2, 1, 3, 2, 5 ]

        第一步:

                先将所有的数异或(相同为0,不同为1,满足交换律),因为只有两个元素只出现一次,其余均出现两次。那么出现两次的数异或后就变成了0,最后就剩两个不同的数异或

 

         第二步:

                观察发现,异或后的第一次出现1的位置,在只相同一次的两个数中,在这位置不是0就是1.只要这个二进制位的1,别问为什么,我不知道(多观察)。最后你会求得 

                                                0010

        第三步:

                你在用第二步得到的值与例子中的值挨个与运算。

 你会发现变成两组的数据。有一组数据进行与运算后变成了0。所以用代码怎么实现呢?

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        int val = 0;
        for(auto& n1:nums)
        {
            val ^= n1;
        }
        // 0000 0101
        // 0000 0011
        // 异或后
        // 0000 0110 -> val

        int i = 0;
        // val二进制第一次出现1的位置 i
        // 原只相同一次的两个数,在这位置不是0就是1.
        for(;i<32;i++)
        {
            if(val & (1<<i)) // (1<<i)  ->  0000 0010
            {
                break;
            }
        }

        int num1 = 0;
        int num2 = 0;
        for(auto& n2 : nums)
        {
            // 分组的思想
            if(((1<<i) & n2) == 0) 
            {
                num1 ^= n2; // 1 1 5
            }else{
                num2 ^= n2;  // 2 3 2
            }
        }
        vector <int> v;
        v.push_back(num1);
        v.push_back(num2);
        return v;
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值