思路真的很巧妙。
为什么要强调剩下的数字都出现了两次,而不是出现多次?
考虑到每个数字,自己和自己异或结果是0。
把数组中所有数字做异或,重复出现的数字被消掉了,最后的结果是要求的两个只出现一次的数字的异或值。
因为要求的这两个只出现一次的数字一定不相同,所以它们的异或值一定有某些位是1。这两个待求的只出现一次的数就是在这一位上有差异。
于是我们就把看一下这个异或值哪一位有1,再按照这一位把所有的数字分成两拨。
我们把这两拨数字分别异或,最后得到的两个数字即为所求。因为两个待求数字一定是分在这两拨里面,剩下的数都是成双成对的一定会被消掉。
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
int len = data.size();
if (len < 2) return;
int tmp = 0;
for (int i : data)
tmp ^= i;
int pos = find1Pos(tmp);
*num1 = 0, *num2 = 0;
for (int i : data)
compute(pos, num1, num2, i);
}
int find1Pos(int t) {
int res = 0;
while ((( t & 1) == 0) && res < 8*sizeof(int)) {
++res;
t = t >> 1;
}
return res;
}
void compute(int const pos, int *num1, int *num2, int i) {
if (((i >> pos) & 1 )== 0)
*num1 ^= i;
else
*num2 ^= i;
}
};
代码写完总也过不去,最后发现是这句出了问题((t & 1) == 0),一开始我写的是t&1==0,因为&的算术优先级低于==所以结果不对。吃一堑长一智!