一道面试题:
在一个数组中除两个数字只出现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;
}
这是一道很经典的面试题目,曾经在百度的面试题中出现。
转载于:https://blog.51cto.com/sanguonaigao/1532904