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


题目描述

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
解法:首先考虑如果数组中只有一个数字出现一次,其他的数字都出现两次,怎么找出这个只出现一次的数字?

这里需要用到异或运算的性质:一个数字(不管是什么形式的数字,只要其二进制形式确定)和其自身的异或运算的结果一定位0。因此,如果一个数组中只有一个数字出现一次,其他数字都出现了两次,那么将整个数组中元素异或得到的结果就是那个只出现一次的数字。


本题要求出两个数字之外,其他的数字都出现了两次,找出这两个只出现一次的数字。怎么运用上面的思想呢?

1、将数组中元素相互异或的结果设为val,val依然不为0

2、怎么根据这个结果值val,将数组分为两个子数组,使得没有子数组中只有一个只出现一次的数字,其他数字都出现了两次?

val对应的二进制位中至少有一位为1,假设第n位为1。根据数组中元素的第n位是否为1,将数组元素分为两个子数组。这样两个相同的元素肯定被分配到同一个子数组中,并且每个子数组包含一个只出现了一次的数字,而其他的数字都出现了两次。运用上述方法,就可以分别求出这两个数字。


class Solution {
public:
    void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
        //相同的数字异或的结果为0
        if (data.size() == 0 || data.size() < 2 || num1 == NULL || NULL == num2){
            return;
        }
    
        int val = 0;
        for (size_t i = 0; i != data.size(); i++){
            val = val ^ data[i];
        }
        //找出val的二进制形式从右到左第一个1出现的位置
        int tmp = 0x1;
        while ((val & tmp) == 0){
            tmp = tmp << 1;
        }
       //分为两个子数组,求出这两个只出现了一次的数
        *num1 = 0;
        *num2 = 0;
        for (size_t i = 0; i != data.size(); i++){
            if ((data[i] & tmp) == 0){
                *num1 = *num1 ^ data[i];
            }
            else {
                *num2 = *num2 ^data[i];
            }
        }
   
        return;


    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值