问题:数组中,有三个数只出现1次,其他都出现2次。找出来那三个数。
注意:由于3是奇数,所以这三个数都相同的位异或起来也会是1。
思路:假设将数组中所有数异或起来之后。
假如某一位为0,说明所求那三个数在这一位是000或者110. 假如某一位为1,说明所求那三个数在这一位是100或者111。因此根据这个异或结果没办法找出一个位进行有效的分组。
需要用异或结果再分别于数组的每个数进行二次异或,找出三个数中的其中一个数,其二次异或结果跟另外两个的二次异或结果不同。
#include<iostream>
using namespace std;
unsigned int setbit(unsigned int a)
{
return (a & (~(a-1))); //只保留最右边的1
}
int main()
{
int A[] = {10,14,2, 3,3,4,4,5,5,6,6,7,7,9,9,12,12,13,13};
int n = sizeof(A)/sizeof(int);
unsigned int norresult = 0;
unsigned int flag = 0;
for(int i=0;i<n;i++)
norresult ^= A[i];
for(int i=0;i<n;i++)
flag ^= setbit(norresult^A[i]);
flag = setbit(flag);
//用flag来划分数组
unsigned int nor1 = 0;
unsigned int nor2 = 0;
for(int i=0;i<n;i++)
{
if(setbit(norresult^A[i]) == flag)
nor1 ^= A[i];
else
nor2 ^= A[i];
}
cout<<"First num: "<<nor1<<endl; //已经找出第一个数
nor2 = setbit(nor2);
//用nor2来划分数组(不包括以找出的nor1)
unsigned int nor3 = 0;
unsigned int nor4 = 0;
for(int i=0;i<n;i++)
{
if((A[i] ^ nor1) == 0) //注意运算符优先级
continue;
if((nor2 & A[i]) == 0) //注意运算符优先级
nor3 ^= A[i];
else
nor4 ^= A[i];
}
cout<<"Second num: "<<nor3<<endl;
cout<<"Third num: "<<nor4<<endl;
return 1;
}
与之类似的问题:除了~个数出现~次,其他的数都出现~次。
参考自:http://zhedahht.blog.163.com/blog/static/25411174201283084246412/