异或操作的妙用

给一个很大的数组,里面有两个数只出现过一次,其他数都出现过两次,把这两个数找出来

void getNum(int a[],int length)
{
    int s = 0;//保存异或结果
    for(int i=0;i<length;i++)
    {
        s=s^a[i];
    }
    int temp1 = s;     //临时保存异或结果
    int temp2 = s;     //临时保存异或结果
    int k=0;
    while((temp1&1) == 0)        //求异或结果中位为1的位数
    {
        temp1 = temp1>>1;
        k++;
    }
    for(int i=0;i<length;i++)
    {
        if((a[i]>>k)&1)          //将s与数组中第k位为1的数进行异或,求得其中一个数
        {
            s=s^a[i];
        }
    }
    cout<<s<<" "<<(s^temp2)<<endl;             //(s^temp2)用来求另外一个数
}



假设二个不同数值是a,b;那么 s = a^b; 然后求的s中第一次出现1的位置k,根据异或运算特性,第一次出现1的地方就是这二个数位有区别的地方,比如1001 0101 与 1100 0001 得到异或结果是0101 0100 .那么第一次出现1的地方是第三位,a的第三位是1而b是0 。 接着遍历数值,找出第三位是1的数值就异或,得到的结果就是其中一个数与其他出现二次的数求异或,因为出现二次的数异或得到为0所有最后结果就是所求其中一个数。
最后s与该数求异或就得到另一个数。

转载于:https://my.oschina.net/wizardpisces/blog/208573

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值