题目
【一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。】
方法一:采用STL中的multiset 容器
1、分析
因为数组中只有两个数字只出现一次,其他数字都出现两次,可以使用 multiset 中的 count() 函数来找出。
2、代码
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
multiset<int> mp;
for(auto &i:data)
{
mp.insert(i);
}
bool flag=true;
for(multiset<int>::iterator it=mp.begin();it!=mp.end();it++)
{
if(mp.count(*it)==1 && flag)
{
*num1=*it;
it++;
flag=false;
}
if(mp.count(*it)==1)
{
*num2=*it;
break;
}
}
}
};
方法二:
1、分析
因为数组中只有两个数字出现一次,其他的数字都出现了两次,所以对该数组进行异或操作,结果一定是只出现一次的这两个数进行异或的结果。因为其他的数字都出现了两次,相同的数字进行异或结果为0。这样可以将该数组分成两个子数组,每个子数组中只有一个出现一次的数字,其他的数字均出现两次。这样对两个子数组进行异或操作后的结果就是只出现一次的那个数了。
将该数字分成两个子数组,且每个子数组只含一个出现一次的数字,需要首先找到数组异或的结果中第一个1的位置,然后将每个数字的该位置的数与其进行比较,该位为1的数字在一组,该位为0的数字在一组。这样便可以将其合理的分开来。
2、代码
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
if(data.size()<2)
return ;
int exor=0;
//第一次将数组进行异或操作,来得到两个只出现一次的数的异或结果
for(vector<int>::iterator it=data.begin();it!=data.end();++it)
{
exor^=*it;
}
unsigned int firstIndex=GetFirstIndex(exor);
*num1=0,*num2=0;
for(int i=0;i<data.size();++i)
{
if(IsBitOne(data[i],firstIndex))
*num1^=data[i];
else
*num2^=data[i];
}
}
//求第一次出现1的位置
unsigned int GetFirstIndex(int num)
{
unsigned int index=0;
while(((num & 1)==0) && (index<8*sizeof(int)))
{
num=num>>1;
++index;
}
return index;
}
//分组的判读依据
bool IsBitOne(int k, unsigned int index)
{
k=k>>index;
return (k & 1)==1;
}
};