# 寻找数组中只出现一次的数

#include <iostream>
using namespace std;

// Find the index of first bit which is 1 in num (assuming not 0)
unsigned int FindFirstBitIs1(int num)
{
int indexBit = 0;
while (((num & 1) == 0) && (indexBit < 32))
{
num = num >> 1;
++ indexBit;
}
return indexBit;
}

// Is the indexBit bit of num 1?
bool IsBit1(int num, unsigned int indexBit)
{
num = num >> indexBit;
return (num & 1);
}

// Find two numbers which only appear once in an array
// Input: data - an array contains two number appearing exactly once,
void FindNumsAppearOnce(int data[], int length, int &num1, int &num2)
{
if (length < 2)    return;
// get num1 ^ num2
int resultExclusiveOR = 0;
for (int i = 0; i < length; ++ i)
resultExclusiveOR ^= data[i];

// get index of the first bit, which is 1 in resultExclusiveOR
unsigned int indexOf1 = FindFirstBitIs1(resultExclusiveOR);
num1 = num2 = 0;
for (int j = 0; j < length; ++ j)
{
// divide the numbers in data into two groups,
// the indexOf1 bit of numbers in the first group is 1,
// while in the second group is 0
if(IsBit1(data[j], indexOf1))
num1 ^= data[j];
else
num2 ^= data[j];
}
}

int main()
{
int a[8] = {2,3,6,8,3,2,7,7};
int x,y;
FindNumsAppearOnce(a,8,x,y);
cout<<x<<"\t"<<y<<endl;
return 0;
}

#include <iostream>
using namespace std;

int lowbit(int x)
{
return x & ~(x - 1);
}

void Find2(int seq[], int n, int& a, int& b)
{
int i, xors = 0;
for(i = 0; i < n; i++)
xors ^= seq[i];

int diff = lowbit(xors);

a = 0,b = 0;
for(i = 0; i < n; i++)
{
if(diff & seq[i]) //与运算，表示数组中与异或结果位为1的位数相同
a ^= seq[i];
else
b ^= seq[i];
}
}

//三个数两两的异或后lowbit有两个相同，一个不同，可以分为两组
void Find3(int seq[], int n, int& a, int& b, int& c)
{
int i, xors = 0;
for(i = 0; i < n; i++)
xors ^= seq[i];

int flips = 0;
for(i = 0; i < n; i++) //因为出现偶数次的seq[i]和xors的异或，异或结果不改变
flips ^= lowbit(xors ^ seq[i]); //表示的是：flips = lowbit(a^b) ^ lowbit(a^c) ^ lowbit(b^c)

//三个数两两异或后lowbit有两个相同，一个不同，可以分为两组
//所以flips的值为：lowbit(a^b) 或 lowbit(a^c) 或 lowbit(b^c)

//得到三个数中的一个
a = 0;
for(i = 0; i < n; i++)
{
if(lowbit(seq[i] ^ xors) == flips)     //找出三个数两两异或后的lowbit与另外两个lowbit不同的那个数
a ^= seq[i];
}

//找出后，与数组中最后一个值交换，利用Find2，找出剩余的两个
for(i = 0; i < n; i++)
{
if(a == seq[i])
{
int temp = seq[i];
seq[i] = seq[n - 1];
seq[n - 1] = temp;
}
}

//利用Find2，找出剩余的两个
Find2(seq, n - 1, b, c);
}
//假设数组中只有2（010）、3（011）、5（101）三个数，2与3异或后为001，2与5异或后为111，3与5异或后为110，
//则flips的值为lowbit(001)^lowbit(111)^lowbit(110)= 2 ，当异或结果xors与第一个数2异或的时候，得到的就是3与5异或的结果110，其lowbit值等于flips，所以最先找出来的是三个数中的第一个数：2

int main(void)
{
int seq[]={ 2,3,3,2,4,6,4,10,9,8,8 };
int a,b,c;
Find3(seq, 11, a, b, c);
cout<<a<<endl;
cout<<b<<endl;
cout<<c<<endl;

return 0;
}
posted @ 2016-11-03 20:34  Evil_XJZ  阅读(297)  评论(0编辑  收藏