題目
【一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。】
方法一:採用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;
}
};