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

数组中只出现一次的数字

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

思路:

  • 先来看一个比较简单的情况,如果数组中只有一个数字出现一次,其他都出现两次。那么我们应该可以想到异或运算。异或运算有一个比较好的性质是:相同为0,相异为1。也就是说,任何一个数字异或它自己都等于0,而0异或任何数都等于那个数。因此,从头到尾依次异或数组中的每个数字,那么最终结果刚好是那个只出现一次的数字,重复的数字在异或过程中被抵消了。对于这道题,可以把数组分为两个数组,这数组中只有一个数字是出现一次的,其他的都出现两次,然后对这两个数组分别遍历异或。这样就找到了这两个数字。

具体思路

  • 采取异或思想,可以遍历数组,进行异或,由于数组中除了两个数字之外,其他的数字都出现了两次,这些成对的数字进行异或就相互抵消了,所以数组最后异或结果为两个只出现一次数字的异或,由于这两个数字不同,所以异或结果肯定不为0,也就是这个异或结果一定至少有一位是1,我们在结果中找到第一个为1的位的位置,记为第n位。接下来,以第n位是不是1为标准,将数组分为两个子数组,第一个数组中第n位都是1,第二个数组中第n位都是0。这样,便实现了我们的目标。最后,两个子数组分别异或则可以找到只出现一次的数字。

具体代码

class Solution {
public:
    void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
        int length = data.size();
        if(length < 2){
            return;
        }
        // 对原始数组每个元素求异或
        int resultExclusiveOR = 0;
        for(int i = 0; i < length; ++i){
            resultExclusiveOR ^= data[i];
        }
         int indexOf1 = FindFirstBitIs1(resultExclusiveOR);
        
        *num1 = *num2 = 0;
        for(int j = 0; j < length; j++){
            if(IsBit1(data[j], indexOf1)){
                *num1 ^= data[j];
            }
            else{
                *num2 ^= data[j];
            }
        }
    }
private:
    // 找到二进制数num从右往左数第一个为1的位数,比如0010,第一个为1的位数是2。

    int FindFirstBitIs1(int num){
         int indexBit = 0;
        // 只判断4个字节的,最大不能超过num取值范围
        while((num & 1) == 0 && (indexBit < 8 * sizeof( int))){
            num = num >> 1;
            indexBit++;
        }
        return indexBit;
    }
    // 判断第indexBit位是否为1

    bool IsBit1(int num,  int indexBit){
        num = num >> indexBit;
        return (num & 1);
    }
};


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值