题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
分析:
方法(1):先遍历一遍数组,计算出所有元素亦或结果sum,按照sum是1的比特位将原数组分成2组,那两个单独的数组必然被分到两组,因为是他俩不同的比特位才造成sum的1的,然后亦或其中一组找到其中一个数组n1,然后用sum亦或这个n1得到n2。
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
int size=data.size();
int sum=0;
//所有元素亦或结果
for(int i=0;i<size;i++)
{
sum=sum^data[i];
}
int flag=0;
for(int i=0;i<32;i++)
{
if(((sum>>i)&1)==1)
{
flag=i;//记录下sum右移i位时是1
break;
}
}
vector<int> v;
for(int i=0;i<size;i++)
{
if(((data[i]>>flag)&1)==1)//把这一位是1的放在v中
{
v.push_back(data[i]);
}
}
int s=0;
for(int i=0;i<v.size();i++)//找出其中一个
{
s=s^v[i];
}
*num1=s;
*num2=sum^s;
}
方法(2):排序,比较相邻两个元素
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
int size=data.size();
int sum=0;
vector<int> v;
sort(data.begin(), data.end());
int i=0;
while(i<size)
{
if(i+1<size && data[i]==data[i+1])
{
i+=2;//跳过2个
}
else
{
v.push_back(data[i]);
i++;//跳过1个
}
}
*num1=v[0];
*num2=v[1];
}
方法(3):借助set,遍历数组,元素在的就删除并且不插入当前的,不在则插入,则set最后剩下的就是那两个数据
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
int size=data.size();
int sum=0;
set<int> s;
set<int> ::iterator it;
for(int i=0;i<size;i++)
{
it=s.find(data[i]);
if(it==s.end())//没有就插入
{
s.insert(data[i]);
}
else
{
s.erase(it);
}
}
it=s.begin();
*num1=*it;
it++;
*num2=*it;
}
方法(4):所有元素亦或结果是sum,然后用sum亦或里面的一个元素看是否能翻译出另一个元素(a^b=sum,sum^a=b)
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
int size = data.size();
int sum = 0;
//所有元素亦或结果
for (int i = 0; i<size; i++)
{
sum = sum ^ data[i];
}
//找出其中一个(sum^a=b,a和b是那两个单独的数字)
for (int i = 0; i<size; i++)
{
for (int j = i + 1; j<size; j++)
{
if ((data[i] ^ sum) == (data[j]))
{
*num1 = data[i];
*num2 = data[j];
break;
}
}
}
}