题目
数组中只出现一次的两个数字
一个整型数组里除两个数字之外,其他数字都出现两次。请写程序找出这两个只出现一次的数字。要求时间复杂度为O(n),空间复杂度为O(1)
例如:输入数组{2,4,3,6,3,2,5,5},因为只有4和6这两个数字只出现了一次,其他数字都出现了两次,所以输出4和6.
解题思路
采用异或运算的性质:任何一个数字异或它自己都等于0
如果我们从头到尾依次异或数组中的每个数字,那么最终的结果刚好是那个只出现一次的数字,因为成对出现两次的数字全部在异或中抵消了。
- 从头到尾依次异或数组中的每个数字,那么最终得到的结果就是两个只出现一次的数字的异或结果。
- 找出异或结果中第一个为1的位的位置,记为第n位
- 以第n位是不是1为标准把原数组分为两个子数组,第一个子数组中美格尔数字的第n位都是1,第二个子数组中每个数字的第n位都是0.
代码
class Solution{
public:
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);
}
void findNumsappearonce(int a[],int length,int *num1,int *num2)
{
if(a == NULL || length < 2)
{
return ;
}
int resultExclusiveOR = 0;
for(int i = 0;i < length; ++i)
{
resultExclusiveOR ^= a[i];
}
//cout << "resultExclusiveOR: " << resultExclusiveOR << endl;
int indexOf1 = FindFirstBitIs1(resultExclusiveOR);
//cout << "indexOf1: " << indexOf1 << endl;
*num1 = *num2 = 0;
for(int j = 0;j< length;++j)
{
if(IsBit1(a[j],indexOf1))
{
*num1 ^= a[j];
//cout << "num1: " << *num1 << endl;
}
else
{
*num2 ^= a[j];
//cout << "num2: " << *num2 << endl;
}
}
}
};
网友评论