题目:
一个整型数组里除了2个数字之外,其他的数字都出现了两次。请写程序找出这2个只出现一次的数字。
思路:
和前一篇文章类似。利用位运算的 "异或" 实现。
2个相同的数异或=0
但是这样遍历完数组所有元素之后,得到的是两个只出现一次的数异或的结果。
要想分别得到这两个数,还需要进一步思考。
按照上一篇文章的思路,我们需要分别将这两个数放在2个不同的子数组,每个数都按照异或求得。
大数组分成两个子数组可按照下述思路:
找出异或结果某位为1的最低位置,根据这一特性,将原数组分为那一位为1和不为1。
例如:原始数组为1 1 2 2 3 4 所有元素异或结果为7。位为1的最低位是最低那一位。
按照最低那一位是否为1将原数组分为以下两个子数组:1 1 3 和 2 2 4
这样异或两个子数组就可以分别得到3和4。
贴代码:
#include <iostream>
#include <vector>
using namespace std;
// 找出数组中只出现一次的数
void FindNumsAppearOnce(vector<int> data, int* num1, int *num2)
{
if (data.size() < 2)
{
return;
}
int xorRes = 0;
for(unsigned int i = 0; i < data.size(); ++i)
{
xorRes ^= data[i];
}
int pos = 1;
// 找出所有数的异或结果 位为1的最低位(pos)
while((xorRes & pos) == 0)
{
pos <<= 1;
}
*num1 = 0;
*num2 = 0;
// 将原数组划分为pos位为1 和 pos不为1 的两个子数组
for(unsigned int i = 0; i < data.size(); ++i)
{
// 原数组中
if ( (pos & data[i]) == 0 )
{
*num1 ^= data[i];
}
else
{
*num2 ^= data[i];
}
}
}
int main(void)
{
int a[] = {1,1,2,2,3,4};
vector<int> v(a, a + 6);
int num1, num2;
FindNumsAppearOnce(v, &num1, &num2);
cout<<"num1 = "<<num1<<endl;
cout<<"num2 = "<<num2<<endl;
return 0;
}