求解数组中唯一出现奇数次的数,很简单。直接 xor 整个数组,偶数次xor为0,只剩下出现奇数次的数的xor。
基于此,假设数组中两个出现奇数次的数为a, b. 对数组xor结果为R,则R = a ^b. 更进一步,R二进制中的每一个1必定只出现在a或b中!
试想如果我们单独考虑R二进制最低位1(具体的十进制值并不关心),然后将数组划分成两个集合,一个集合中的数该位为1,另一个集合该位为0.试想a和b必定不在相同的集合中!且每个集合中只包含一个出现奇数次的数!然后对每个集合xor即可分别得到num1和num2!
求解整数最低位1可使用补码的技巧: low_bit = x ~ -x
。 -x
是对二进制 x
取反加1,加1会递推原本 x
在最低位1后面的0,直到恢复 x
最低位1.
class Solution { public: void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) { int x = 0; for (auto v: data) x ^= v; int low_bit = x & -x; for (auto v: data) { if (v & low_bit) *num1 ^= v; else *num2 ^= v; } } };