一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

在这里插入图片描述
方法:位运算(异或和按位与)

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* singleNumbers(int* nums, int numsSize, int* returnSize){
    int ret = 0;
    for(int i = 0;i<numsSize;i++)
    {
        ret^=nums[i];
    }
    int k = 0;
    while(((ret>>k)&1)!=1)
    {
        k++;
    }
    int ret1 = 0,ret2 = 0;
    for(int i = 0;i<numsSize;i++)
    {
        if(((nums[i]>>k)&1)==1)
        {
            ret1^=nums[i];
        }
        else
        {
            ret2^=nums[i];
        }
    }
    int* retArr = (int*)malloc(sizeof(int)*2);
    retArr[0] = ret1;
    retArr[1] = ret2;
    *returnSize = 2;
    return retArr;
}

思路:

  1. 首先将数组里的所有数都按位异或,由于有两个数不同。因此结果会是这两个不同的数的异或。

  2. 下一步我们就要将这两个数字分开,怎么分开呢?
    我们看异或后得到的数字,看它第几位是1.(因为异或后得到1可以推出两个不同的数的这一位二进制不同)。

  3. 然后我们遍历数组,把这一位是1的放在一边,这一位是0的放在另一边。并将两边分别异或。由于这两个不同的数这两位二进制位不同,因此它们肯定在不同的两边,这样就分开了。

  4. 对两边的数分别进行异或。剩下的数肯定都是成双成对出现了,异或就能消掉。

  5. 然后再把这两个数放进retArr里

注:由于位运算符的优先级很低很低,比赋值运算符还低。因此在移位的时候要用括号括起来。这里是大坑,博主踩过很多次了!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值