Q:一个整型数组里只有两个数字只出现一次,其他数字都出现了两次,请找出这两个只出现一次的数字
解题思路:
- 通过异或相关知识我们可以知道,成对出现的数字异或后结果为0,那么将这组数据一次异或后的结果就是只出现一次的两个数字异或的结果
- 观察异或结果,比特位为1的就是只出现一次的两个数字比特位不同的位,通过移位并与1结果可以找到第一个比特位不同的位
- 根据该比特位是否为1,可以将这组数据分为两组,成对出现的数字肯定会在同一组,因为它们的所有比特位都相同,与1后的结果也相同
- 只出现一次的两个数字肯定在不同组,因为它们的该位比特位不相同,与1的结果肯定也不相同
- 将分成的两组数据分组异或后的结果就是这两个只出现一次的数字
举例理解:
2,2,1,3,3,4,4,5
异或后结果为:0100,刚好为1和5异或后的结果
1:0001
5:0101
1和5第一个不相同的比特位是第三位
之后根据该比特位分组后找到两个只出现一次的数字
代码:
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
int len=data.size();
if(len==2)
return;
int sum=data[0];
for(int i=1;i<len;++i)
{
sum=sum^data[i]; //计算这组数据异或后的结果
}
if(sum==0)
return;
int index=0;
while((sum&1)==0)
{
sum=sum>>1;
++index; //找到第一个只出现一次的两个数字不同的比特位
}
*num1=0;
*num2=0;
for(int i=0;i<len;++i)
{
if(isThis(data[i],index))
*num1^=data[i];
else
*num2^=data[i];
}
}
bool isThis(int x,int index)
{
x=x>>index;
return x&1;
}
};