05.找单身狗.练习题

//

//版本1:有一个数组,其中只有一个数字出现1次,其余数字都出现了2次

//例如:1 2 3 4 5 1 2 3 4

//

//版本2:

//一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。

//例如: 1 2 3 4 5 1 2 3 4 6

// //001

// //010

// //011

// //100

// //101 110

// //

// 编写一个函数找出这两个只出现一次的数字。

//

//分组:

//分组的要领,就是讲2个单身狗必须放在2个组,同时每个组剩余的数字都是成对出现的

//

//5^6

//101

//110

//011

//以第一位分割

//5 1 1 3 3

//6 2 2 4 4

//以第二位分割:为1的在一起,为0的在一起

//5 1 1 4 4

//6 2 2 3 3

运算符

描述

实例

&

按位与操作,按二进制位进行"与"运算。运算规则:

0&0=0;

0&1=0;

1&0=0;

1&1=1;

(A & B) 将得到 12,即为 0000 1100

|

按位或运算符,按二进制位进行"或"运算。运算规则:

0|0=0;

0|1=1;

1|0=1;

1|1=1;

(A | B) 将得到 61,即为 0011 1101

^

异或运算符,按二进制位进行"异或"运算。运算规则:

0^0=0;

0^1=1;

1^0=1;

1^1=0;

(A ^ B) 将得到 49,即为 0011 0001

~

取反运算符,按二进制位进行"取反"运算。运算规则:

~1=-2;

~0=-1;

(~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。

<<

二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。

A << 2 将得到 240,即为 1111 0000

>>

二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。

A >> 2 将得到 15,即为 0000 1111

//n*n =100*100 =10000
//把所有数组异或在一起
//把两个单身狗异或在一起,但是不知道谁是单身狗,就把所有数字异或在一起,异或时相等的为0,七十九把不是单身狗的数字刨除了
void find_single_dog(int arr[], int sz, int single_dog[])
{
    int ret = 0;
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        ret ^= arr[i];
    }
    //计算ret的哪一位二进制位是1//ret32位,进行异或
    int pos = 0;
    for (i = 0; i < 32; i++)
    {
        if (((ret >> i) & 1) == 1)//都为1才为1
        {
            pos = i;
            break;
        }
    }
    for (i = 0; i < sz; i++)
    {
        if (((arr[i] >> pos) & 1) == 1)
        {
            single_dog[0] ^= arr[i];
        }
        else
        {
            single_dog[1] ^= arr[i];
        }
    }
}

int main()
{
    int arr[] = { 1,2,3,4,8,1,2,3,4,6 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    int single_dog[2] = {0};

    find_single_dog(arr, sz, single_dog);
    printf("%d %d\n", single_dog[0], single_dog[1]);
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值