1.题目描述:
一个整型数组里除了两个数字之外,其他的数字都出现了偶数次。请写程序找出这两个只出现一次的数字。
2.思路分析:
这种类型的题属于技巧题,考察了异或运算的性质。一个数与自己按位异或得到0,一个数与0异或得到它本身,同时异或运算满足交换律与结合律(异或运算的性质)。因此,当数组中只有一个数字出现奇数次,其他数字出现偶数次时,把该数组中的数从左到右依次做异或运算,可以得到那个为出现次数为奇数次的数。
可是在本题中,有两个数字只出现一次,此时将数组中的所有数字依次做异或运算之后,会得到一个不为0的数,该数中除去符号位之外数值为1的位置对应于这两个数在该位置一个为0一个为1,根据这个可以将该数组分为两份,一份在该位置为1,一份在该位置为0,对两份数组中的数字分别做异或运算就可以得到只出现一次的两个数字。
3.代码:
代码如下:
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2)
{
int size = data.size();
int firstbit = 0;
int flagbit = 0;
for(int i = 0; i<size; i++)
{
firstbit = firstbit ^ data[i];
}
flagbit = FindFlagBit(firstbit);
for(int i = 0; i<size; i++)
{
if(isOne(data[i], flagbit))
{
*num1 = *num1 ^ data[i];
}
else
{
*num2 = *num2 ^ data[i];
}
}
}
private:
int FindFlagBit(int firstbit)
{
int num = 0;
while((firstbit & 1) == 0 && num < 8 * (sizeof(int)))
{
num++;
firstbit = firstbit >> 1;
}
return num;
}
bool isOne(int num, int flagbit)
{
bool flag;
if(((num >> flagbit) & 1) == false)
{
flag = false;
}
else
{
flag = true;
}
return flag;
}
};
4.编程实现中遇到的问题:
在while循环的判断条件中,按位与&运算符的优先级是低于==运算符的(运算符优先级),此时下面这个写法是错误的
while((firstbit & 1 == 0) && (num < 8 * (sizeof(unsigned int))))