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

我们知道,两个相同的数字异或后为0,两个不同的数字异或一定是不为0的.

0^0=0;

0^1=1;

1^1=0;

 因此我们可以让这个数组里面的所有元素异或,异或后的结果就是这两个只出现一次的数字.

例如nums里的元素为 1,1,2,2,3,4,4,5,6,6.

1^1^2^2^3^4^4^5^6^6=3^5=6

   0000 0011

^ 0000 0101

= 0000 0110  (异或后的结果)

现在就以上面的示例分析.

题目的要求是找到这两个数字,现在我们得出来的是这两个数异或后的结果,我们知道0和1的出现是看这两个数对应的位是否相同,可以看到异或后结果的第二(N)位为1,说明这两个数的对应的位是不同的.因此我们可以想是否可以利用这一个位来分离这个数组中只出现一次的两个数字,这显然是可行的.

用这一个位对nums数组进行异或,结果为1的放在一个数组中,结果为0的放在另一个数组中.

参照上面例子给出的元素

第二位为1的元素有2,2,3,6,6

第二位为0的元素有1,1,5,4,4

因此这个问题现在就被简化成在一个数组里,只有一个只出现一次的数字.因此很简单,就只需要用0分别异或这两个数组就行了.

0^2^2^3^6^6=3;

0^1^1^5^4^4=5;

int* singleNumber(int* nums, int numsSize, int* returnSize){
    int ret=0;
    int i=0;
    
  //ret为异或后的结果
    for(i=0;i<numsSize;i++)
    {
        ret^=nums[i];
    }

  //m是第N位为1的数,用来分离两个特别的数
    int  m=0;
    while(m < 32)
    {
        if(ret & (1<<m))
        break;
        else
        ++m;
    }
      int x1=0;
      int x2=0;
    for(i=0;i<numsSize;i++)
    {
//分离两个数
        if(nums[i] & (1<<m))
        x1^=nums[i];
        else
        x2^=nums[i];
    }
    int *Array=(int*)malloc(sizeof(int)*2);
    Array[0]=x1;
    Array[1]=x2;
    *returnSize=2;
    return Array;
    

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值