剑指offer:40.数组中只出现一次的数字

40.数组中只出现一次的数字

题目描述

  • 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

 

解题思路

下面的思路来自《剑指offer》。

  • 将问题转化为只有一个数字只出现了一次。首先考虑数组中只有一个数字只出现了一次,只需要将数组中每个数字进行异或,最后得到的数字就是那个只出现了一次的数字,因此其他数字都是出现两次的,在异或的过程中被消掉了。

    然后问题就变成如何将数组拆分成两组(不一定要把两组数字拷贝到新的数组中),每组中都只有一个数字只出现一次。仍然可以通过异或的方式进行分组,将整个数组异或一遍,最后得到的结果肯定不是0,因为有两个数字是不一样的,而且这个结果就是这两个只出现一次的数字异或的结果,因此可以找到异或结果中一个为1的位,可以就取从右向左第一个为1的位,假如是第n位,这两个数字在这一位上肯定是不一样的,而其他数字在这一位上一定是两两相同的,因此可以以这一位为依据,这一位为1的所有数字分为一组,这一位为0的数字分为另一组,再求出这两组中只出现一次的数字就可以解决问题了。

    在第二次遍历的时候可以通过判断这个数字的第n为是否是1来判断这个数字属于哪一组,这样就不用把两组数字分别拷贝出来了,整个过程中就只需要对整个数组遍历两次即可。因此整个过程时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)

  • 注意:有&与运算的式子要加小括号,不然运算顺序可能会有问题,因为==的优先级比&更高,比如num&1==0就会先算后面的。

 

代码

  • C++
class Solution {
private:
    int findFirstBit1(int num){
        int bitIndex = 0;
        int bitInt = 8*sizeof(int);
        // 注意&的式子要加小括号,因为==优先级更高
        while(((num&1)==0) && bitIndex<bitInt){
            bitIndex++;
            num = num >> 1;
        }
        return bitIndex;
    }
public:
    void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
        int length = data.size();
        if(length<2) return;
        if(length==2){
            *num1 = data[0];
            *num2 = data[1];
            return;
        }
        
        int XorResult = data[0];
        for(int i=1; i<length; i++) XorResult ^= data[i];
        
        int flag = 1 << findFirstBit1(XorResult);
        
        *num1 = *num2 = 0;
        for(int i=0; i<length; i++){
            // 注意&的式子要加小括号,因为==优先级更高
            if((flag&data[i])==0) *num1 ^= data[i];
            else *num2 ^= data[i];
        }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值