<pre name="code" class="cpp">// 有三个数出现一次,其他均出现两次,找出这三个数.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#define BIT_SIZE 32
#define isON(n, i) ((n)&1<<(i))
// 0x0111
// 0x1011
// 0x1100
// 0x0101
// 0x1001
// 0x1011
void findNumber2(unsigned int *arr, int size, unsigned int &A, unsigned int &B, unsigned int &C)
{
int tempA, tempB;
int countA, countB;
int firstNum;
int secondNum;
int thirdNum;
int findNumIdx = 0;
int findArray[3] = {0};
int i, j;
for (i = 0; i < BIT_SIZE; i++)
{
int tempA = 0, tempB = 0;
int countA = 0, countB = 0;
for (j = 0; j < size; j++)
{
if (isON(arr[j],i))
{
countA++;
tempA ^= arr[j];
}
else
{
countB++;
tempB ^= arr[j];
}
}
if (countA & 0x1)
{
//bit i 出现了 基数次
if (tempB != 0)
{
//如果三个只出现一次的数的第i位都是ON,那么tempB必定为0
//如果三个只出现一次的数中有两个第i位为On,那么countA为基数就不成立
//如果三个只出现一次的数中只有一个第i位为On,那么另外两个只出现一次的数的异或必定不为0
firstNum = tempA;
break;
}
}
else
{
//bit i 出现了 偶数次
if (tempB != 0 && abs(countA-countB)<3)
{
// 这 3 个数中的一个没有出现这个这个 bit i, 因此这个 tempB 就是不包含这个 bit i 的 3 个数中的其中一个
//如果三个只出现一次的数中有两个的第i位为On,那么tempB(如果tempB不为0)就是那一个第i位不为On的那个数
//如果三个只出现一次的数没有一个的第i位为On,那么tempB
firstNum = tempB;
break;
}
}
}
unsigned int merged = 0;
for (int idx = 0; idx < size; idx++)
{
merged ^= arr[idx];
}
merged ^= firstNum;
secondNum = 0;
for (int k = 0; k < BIT_SIZE; k++)
{
if (isON(merged, k))
{
for (int m = 0; m < size; m++)
{
if ((arr[m] != firstNum) && isON(arr[m], k))
{
secondNum ^= arr[m];
}
}
break;
}
}
thirdNum = merged ^= secondNum;
A = firstNum;
B = secondNum;
C = thirdNum;
}
int _tmain(int argc, _TCHAR* argv[])
{
unsigned int Array[] = {2,2,4,4,8,8,13,13,10,10,5,0,11};
unsigned int a, b, c;
findNumber2(Array, 13, a, b, c);
return 0;
}