题目:一个整型数组里除了两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度为O(1)。
分析:由于时间复杂度和空间复杂度的限制,不可能用多次遍历数组方法和辅助数组的方法。因此问题比较难以下手。现在考虑如果只有一个数字出现了一次的情况,如果只有一个数字出现了一次,而其他数字都出现了两次,那么,我们可以将数组所有数字进行异或运算,那么最终结果就是这个数字。现在是两个数字,我们需要想办法将这个数组分成量个子数组,儿这两个子数组中分别包含这两个要求的数字,且其他数字都是成对出现,那么将两个子数组分别异或就得到了这两个数。如何分割数组呢?我们先将所有数字异或,得到一个非零的数字,就是这两个数字的异或,所以这两个数字的异或的二进制数中肯定有一位是1,我们根据这个二进制数中第一位为1的位置,将数组所有数字的二进制根据这个位置是否为1分成两个子数组。则这两个数分别被分到了这两个子数组中,且其他数字都是成对出现的。再将这两个数组分别异或就得到了这两个数字。实现如下:
void FindNumsAppearOnce(int data[],int length,int* num1,int* num2)
{
if(data==NULL||length<2)
return;
int resultExclusiveOR=0;
for(int i=0;i<length;i++)
resultExclusiveOR^=data[i];
unsigned int indexOf1=FindFirstBitIs1(resultExclusiveOR);
*num1=*num2=0;
for(int j=0;j<length;j++)
{
if(IsBit1(data[j],indexOf1))
*num1^=data[j];
else
*num2^=data[j];
}
}
unsigned int FindFirstBitIs1(int num)
{
int indexBit=0;
while(((num&1)==0)&&(indexBit<8*sizeof(int)))
{
num=num>>1;
++indexBit;
}
return indexBit;
}
bool IsBit1(int num,unsigned int indexBit)
{
num=num>>indexBit;
return (num&1);
}本文出自 “仙路千叠惊尘梦” 博客,请务必保留此出处http://secondscript.blog.51cto.com/9370042/1587794
原文:http://secondscript.blog.51cto.com/9370042/1587794