描述
一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
示例1
输入:
[1,4,1,6]
返回值:
[4,6]
说明:返回的结果中较小的数排在前面
思路
先考虑另一个问题,一个整型数组里除了一个数字之外,其他的数字都出现了两次,那把所有的数据异或起来,异或的结果就是那一个数字。(因为出现过两次的数字异或起来就抵消了)
对于这个题来说,如果把数字全异或起来,最后异或出来的结果是不同的那两个数的异或,然后随便从异或结果里面找一位1,因为某一位上异或结果是1的话,说明要找两个数,这一位上一个是1,一个是0。那么就可以把原来数组中,这一位是1的分成一组,这一位是0的分成一组。
我们在结果数字中找到第一个为1 的位的位置,记为第N 位。现在我们以第N 位是不是1 为标准把原数组中的数字分成两个子数组,第一个子数组中每个数字的第N 位都为1 ,而第二个子数组的每个数字的第N 位都为0 。
相同的数字每一位都是相同的,因此相同的数字肯定会被分到同一组。
现在我们已经把原数组分成了两个子数组,每个子数组都包含一个只出现一次的数字,而其它数字都出现了两次。因此到此为止,所有的问题我们都已经解决。
c++代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* @param array int整型vector
* @return int整型vector
*/
vector<int> FindNumsAppearOnce(vector<int>& array) {
// write code here
vector<int> result;
int ans1 = 0, ans2 = 0;
int XOR = 0;
for(int i = 0; i < array.size(); i++){
XOR ^= array[i];
}
int t = 1;
while((t&XOR) == 0){
t = t << 1;
}
for(int i = 0; i < array.size(); i++){
if(t&array[i]) //第N位为1的一组
{
ans1 ^= array[i];
}
else{ //第N位 不 为1的一组
ans2 ^= array[i];
}
}
result.push_back(min(ans1, ans2));
result.push_back(max(ans1, ans2));
return result;
}
};