数组中只出现一次的两个不同数字

//大致思路:如果是只有一个出现一次的数字的话,直接全部异或求值最终剩下的就是所求,因为,异或的性质就是,a^a=0,a^0=a;
回到本题目,还是全部进行异或,因为有两个出现一次的数字,所以异或完后剩下的数字就是两个数字异或的值,那么这个数字的
二进制中肯定有一个位是1,这也就表示这两个出现一次的数字的二进制表示中此位上是不同的,我们可以根据此特点将原数组分开
也就是将这两个数字分到不同的数组中去,分别进行异或,这样就可以得到这两个数字。关于求哪个位上为1,我参考了一个大神的
做法,就是一个数与其负数做与运算,因为在机器中数字用二进制表示,那么正数的原码,反码补码相同,但是负数不一样,这样,
正数与负数做与运算,就可以保留一个1,其余全部为0,那么对于这个结果和其他数字做与运算,只要此位不为1,结果就是0;
class Solution {
public:
    int findfirstnumber1(int num)//负数用补码表示,正数原码表示,这样除了最后的一个相同的1,保留其余全部为0;
        {
        return num&(-num);
    }
    bool Isequal(int a,int b)
        {
        int flag=findfirstnumber1(b);
        if((a&flag)==0)
            return false;
        else
            return true;
    }
    void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
           if(data.size()<2)
               return;
        int p=0;
        *num1=0,*num2=0;
        for(int i=0;i<data.size();i++)
            p=p^data[i];
        for(int i=0;i<data.size();i++)
            {
            if(Isequal(data[i],p))
                *num1=*num1^data[i];
            else
                *num2=*num2^data[i];
        }
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值