【问题描述】
接着前一篇文章的问题,若一个数组中所有的整数都出现了两次,仅有两个不同的数字出现一次,找出这两个整数。
【来源】
微软面试题
【思路】
从前一篇文章中可以知道,两个相同的整数进行异或操作,结果为0,这个问题我们也是将所有的整数进行异或操作,左后的结果肯定不是0,由于其他所有的整数都出现了两次,所以进行异或操作后,其他数字都被消除(异或操作后是0),这个非零结果就是那两个出现一次整数异或的结果,我们可以找到这个结果从低位开始第一个二进制不是0的位置,对于两个整数异或后,出现1,说明其中一个整数在这个位置二进制位0,一个为1.因此我们可以找到其中一个整数。知道了其中的一个整数,那么将刚才的结果与这找到的这个整数的反进行与操作,结果就是另一个整数。
【参考程序】
#include <iostream>
#include <Cstdlib>
using namespace std;
int GetFirstOne(int result) //从低位开始,找到第一个二进制位是1的index
{
int idx =0;
while(result)
{
if(result & 1 == 1)
break;
else
result>>1;
idx ++;
}
return idx;
}
int GetNum(int *nums,int idx,int len) //找到其中的一个出现一次的数
{
int r = 1<<idx;
int i,t =0;
for(i =0;i<len;i++)
{
if(nums[i]&r == r)
{
t ^= nums[i];
}
}
return t;
}
int GetOther(int *nums,int idx,int len)
{
int r = 1<<idx;
int i,t =0;
for(i =0;i<len;i++)
{
if(nums[i]&r != r)
{
t ^= nums[i];
}
}
return t;
}
int main()
{
int n,i,*nums,r,idx,num1;
while(cin>>n)
{
nums = (int *)malloc(sizeof(int)*n);
r =0;
i =0;
while(i < n){
cin>>nums[i];
r ^=nums[i];
i++;
}
idx = GetFirstOne(r);
num1 = GetNum(nums,idx,n);
cout<<idx<<endl
<<num1<<endl
<<(r &(~ num1))<<endl;
}
return 0;
}