一、一个数组中有一个数字出现了一次,其余的数字都出现了两次。快速找出只出现一次的那个数字。
思路:位运算中两个相同的数按位异或结果是0,另外0与任何数异或结果就是那个数。因此将数组中所有的元素一起做异或运算,出现两次的元素会消掉,最后只剩那个只出现一次的数字。
二、一个数组中有两个数字出现了一次,其余的数字都出现了两次。快速找出只出现一次的那两个数字。
例如:1,1,2,2,3,3,8,9
借鉴第一个问题的思路,如果能先把数组分成两部分,一部分含有一个目标数字,那接下来就能使用第一个问题的解决方法了。将所有元素做异或运算就相当于两个目标数字做异或运算。两个目标数字不相等,异或之后结果肯定不是0,那么异或的结果某一位为1的话,两个目标元素的这一位肯定不同。这样根据这一位是否为1就可以把原始数组分成两部分。再按照第一题的思路解决。
代码如下:
class Solution {
public:
int Just1NumAppearOnce(vector<int>& data){//只有一个数字出现了一次。
int len = data.size();
if(len <= 0)
return -1;
int ans = data.at(0);
for(int i = 1; i < len; i++)
ans ^= data.at(i);
return ans;
}
int findBit1(int n){//找出哪一位为1
int x = 1;
for(int i = 0; i < 32; i++){
if((x & n) != 0)
return i;
else
x = x << 1;
}
return -1;
}
bool isXBit1(int n, int index){//第index位是否为1
int x = 1;
for(int i = 0; i < index; i++)
x = x << 1;
if((n & x) == 0)
return false;
else
return true;
}
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
*num1 = 0;
*num2 = 0;
int len = data.size();
if(len < 2)
return;
int exclu = data.at(0);
for(int i = 1; i < len; i++)
exclu ^= data.at(i);
int index = findBit1(exclu);
vector<int> data0;
vector<int> data1;
for(int x : data){
if(isXBit1(x, index))
data1.push_back(x);
else
data0.push_back(x);
}
*num1 = Just1NumAppearOnce(data0);
*num2 = Just1NumAppearOnce(data1);
}
};