题目描述

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

思路

首先这道题本可以直接对所出现的数进行计数,然后输出数组中只出现一次的两个数字。

但是题上特地说了一下其他数字都出现了两次,说明题意是想考察的是另一个知识点:

位运算中的异或运算:两个相同的数进行异或时,结果为0

因此如果我们从头到尾依次异或数组中的每一个数字,那么最终得到的结果就是两个只出现一次的数字的异或结果,

由于这两个数字不一样,那么这个异或结果肯定不为0 ,也就是说在这个结果数字的二进制表示中至少就有一位为1 ,

我们在结果二进制中保留最高位的1(假设为第N位),并将其它的都置为0,然后拿这个数与原数组进行与运算,

这样原数组就会被我们分为两个子数组,第一个子数组中每个数的第N 位都为1 ,而第二个子数组的每个数的第N 位都为0 。

现在我们已经把原数组分成了两个子数组,而只出现一次的两个数字也被我们分到了两个不同的子数组中,

因此再对两个子数组进行异或之后就可以得出最终的结果了,而且题上并没有说明要按顺序找出这两个数字,

那么到此为止,问题就被我们解决了。

代码

class Solution {
public:
    void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
        if(data.empty())
            return;
        int x = 0;//用于保存num1和num2的异或结果
        for(int i = 0; i < data.size(); i++)
            x ^= data[i];
        int t = 1;//保留x中第一个1的位置,其它都置为0
        while(x>>1){
            t *= 2;
            x = x>>1;
        }
        *num1 = *num2 = 0;
        for(int i = 0; i < data.size(); i++){
            if(t & data[i]){
                *num1 ^= data[i];
            }
            else
                *num2 ^= data[i];
        }
        return;
    }
};