一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
思路:
先把整个数组的数字异或得到只出现一次的数字异或的结果。因为这个结果是只出现一次的数字异或的结果,所以异或的结果肯定会有 一个1, 然后找到这个异或结果的第一个1出现的位置,比如第n位。
根据这个1出现的位置把原来的数组分组,第n位位1的分到一个数组,不为1的分到另一个数组,
这样只出现一次的数字就会分到不同的数组。由于题目说其他数字只是出现一次,所以而这两个数组里面只有一个元素是只出现一次,就是题目所求的数字
比如 1 1 3 6 3 6 5 7
整个数字异或的结果是res = 5^7 = 0010 第一个1出现的位置(从右边的第零位数起)是第1个位置。
按照第1位(同上从右边的第零位数起)是否为1把数组分成两个数组,
得到{3, 6, 3, 6, 7} {1,1,5 }
两个数组分别自己异或,左边的得到7,右边得到1,所以数组只出现一次的是5 和7
class Solution {
public:
vector<int >sub1;
vector<int >sub2;
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2)
{
int length = data.size();
if(length == 0)
return ;
int ans = 0;
for(int i = 0; i < length; i++)//求整个数组异或的结果
ans ^= data[i];
//cout<<ans<<endl;
int pos = getFirst(ans);//获取ans的第一个1出现的位置
//cout<<pos<<endl;
for(int i = 0; i < length; i++)
{
if(check(data[i], pos))//data[i]在二进制中第pos位是1
sub1.push_back (data[i]);//分到数组sub1
else
sub2.push_back (data[i]);//分到数组sub2
}
int res_num1 = 0, res_num2 = 0;
for(int i = 0; i < sub1.size(); i++)//获得结果
res_num1 ^= sub1[i];
for(int i = 0; i < sub2.size(); i++)
res_num2 ^= sub2[i];
*num1 = res_num1;
*num2 = res_num2;
return ;
}
int getFirst(int ans )//获取ans第一个1的位置
{
int pos = 0;
while(ans)
{
if(ans & 1)
break;
else
{
pos++;
ans>>=1;
}
}
return pos;
}
bool check(int x, int pos)//检验x的第pos位置是否为1
{
x = x>>pos;
if(x & 1)
return true;
else
return false;
}
};