一道面试题:

在一个数组中除两个数字只出现1次外,其它数字都出现了2次, 要求尽快找出这两个数字。

要求:时间复杂度为O(N),空间复杂度为O(1)。

分析:

如果将这道题简单化:

    一个数组中只有一个数字出现一次,其他数字都是成对出现的,这时我们可以根据异或运算符的特性:A^B^A = B; 0 ^ A = A;我们可以将这个数组的全部元素依次做异或元算,结果就是那个只出现一次的数字。


    如果这个数组中出现两个不同的数组,而其他数字均出现两次,假设这两个数组是x,y。那我们如果可以将x,y分离到两个数组。这时这道题就变成两个我们简化之后的版本中的数组了。这样问题就可以得到解决了。由于x,y肯定是不相等的,因此在二进制上必定有一位是不同的。根据这一位是0还是1可以将x,y分开到A组和B组。并且数组中其他元素也可以根据这个方法划分到两个数组中。这时将两个数组分别做异或运算,结果就是这两个数字。


根据上面的解释,不难写出代码。

实现代码如下:

#include "iostream"
using  namespace std;
void printArray(int a[],int n)
{
    for(int i = 0; i < n; ++i)
    {
        cout << a[i] <<" ";
    }
    cout << endl;
}
void findNums(int a[], int n, int& num1, int& num2)
{
    int temp = 0;
    int j;
    for(int i = 0; i < n; ++i)
    {
        temp ^= a[i];
    }
    for(j = 0; j < sizeof(int) * 8; j++)
    {
        if(((temp >> j) & 1) == 1)
        break;
    }
    num1 = 0;
    num2 = 0;
    for(int i = 0; i < n; ++i)
    {
        if(((a[i] >> j) & 1) == 0)
        {
            num1 ^= a[i];
        }
        else
        {
        num2 ^= a[i];
        }
    }
}
int main()
{
    const int MAXN = 10;
    int arr[MAXN] = {1,2,3,4,1,2,3,4,0,5};
    printArray(arr, MAXN);
    int num1,num2;
    findNums(arr, MAXN, num1, num2);
    cout << num1 << " "<< num2 <<endl;
    return 0;
}


这是一道很经典的面试题目,曾经在百度的面试题中出现。