您的位置:首页 > 其它

数组中只出现一次的数字,时间复杂度O(n),空间复杂度O(1)的解法

2015-06-04 10:46 281 查看
题目:一个整型数组里除了两个数组外,其他的数字都出现了两次,要找出这两个数字。

异或运算有一个性质:任何数异或它自己,结果都是0;这样如果题目变成只有一个数字只出现一次,其他数字均出现两次,这样我们从头到尾异或数组中的每一个数字,那么最终的结果就是只出现一次的数字。

如果可以把数组中的数字分成两个子数组,每个数组里面包含一个只出现一次的数字,其他的数字都出现两次,这样按照上面的方法就可以分别求出只出现一次的数字了。首先,我们从头到尾异或数组中的每一个数字,那么得到的结果将是这两个只出现了一次的数字异或后的结果(因为其他出现了两次的数字都在异或中抵消了)。由于这两个数字不相同,所以它们的异或结果的二进制表示中至少有一位是1.我们先找到第一个为1的位的位置,记为第n位。然后我们以第n位是否为1,把原数组分成两个子数组,第一个数组中每个数的第n位都为1,第二个数组中的每个数的第n位都为0,因为两个相同的数字的任意一位都是相同的,所以相同的数肯定分在同一组,这样我们就实现了划分子数组的效果。

参考代码如下:

#include<iostream>

#include<cstdio>

using namespace std;

bool Is1(int n,unsigned int bit)

{

n=n>>bit;

return (n&1);

}

unsigned int FindFirstBit1(int n)

{

int bit=0;

while((n&1)==0&&bit<8*sizeof(int))

{

n=n>>1;

bit++;

}

return bit;

}

void FindNums(int data[],int len,int &num1,int &num2)

{

if(data==NULL||len<2)

return;

int ans=0;

for(int i=0;i<len;i++)

ans=ans^data[i];

unsigned int bit=FindFirstBit1(ans);

for(int i=0;i<len;i++)

{

if(Is1(data[i],bit))

num1=num1^data[i];

else

num2=num2^data[i];

}

}

int main()

{

int num1=0,num2=0;

int data[100];

int len;

scanf("%d",&len);

for(int i=0;i<len;i++)

scanf("%d",&data[i]);

FindNums(data,len,num1,num2);

printf("%d %d",num1,num2);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: