剑指offer-40:数组中只出现一次的数字
目录
1题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。
请写程序找出这两个只出现一次的数字。
2问题解析
可以用位运算实现,如果将所有所有数字相异或,则最后的结果肯定是那两个只出现一次的数字异或 的结果
所以根据异或的结果1所在的最低位,把数字分成两半,每一半里都还有只出现一次的数据和成对出现的数据
这样继续对每一半相异或则可以分别求出两个只出现一次的数字
#include <iostream>
#include <vector>
using namespace std;
bool IsBit(int num,int index)
{
num=num>>index;
return (num&1);
}
int main()
{
vector<int> data={1, 1, 2, 3, 2, 4, 4, 5, 6, 6};
if(data.size()<2) return 0;
int size=data.size();
int temp=data[0];
for(int i=1;i<size;i++)
temp=temp^data[i]; // 异或,相同为0,不同为1
//cout<<temp<<endl; // 输出temp = 6 = 0110
if(temp==0) return 0;
int index=0;
while((temp&1)==0){
temp=temp>>1;
++index;
}
//cout<<index<<endl; //index=1
//如果data={1, 1, 2, 2, 7, 4, 4, 3, 6, 6}; temp=0100; index=2
int num1=0;
int num2=0;
for(int i=0;i<size;i++){
cout<<IsBit(data[i],index)<<endl;
if(IsBit(data[i],index))
num1^=data[i];
else
num2^=data[i];
}
cout<<num1<<" "<<num2<<endl;
}
0
0
1
1
1
0
0
0
1
1
3 5
3答案
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
if(data.size()<2) return;
int size=data.size();
int temp=data[0];
for(int i=1;i<size;i++)
temp=temp^data[i]; //异或,相同为0,不同为1
if(temp==0) return;
int index=0;
while((temp&1)==0){
temp=temp>>1;
++index;
}
*num1=*num2=0;
for(int i=0;i<size;i++){
if(IsBit(data[i],index))
*num1^=data[i];
else
*num2^=data[i];
}
}
bool IsBit(int num,int index){
num=num>>index;
return (num&1);
}
};