题目
思路
我们知道对于异或运算, 0 ⊗ a = a 0 \otimes a = a 0⊗a=a并且 a ⊗ a = 0 a \otimes a = 0 a⊗a=0, 如果存在某种运算 ⊕ \oplus ⊕,使得 0 ⊕ a = a 0 \oplus a = a 0⊕a=a并且 a ⊕ a ⊕ a = 0 a \oplus a \oplus a = 0 a⊕a⊕a=0,那么我们只需要将所有数字使用该运算执行一次即可得到仅出现一次的数字。
我们知道异或运算能够实现 0 ⊗ a = a 0 \otimes a = a 0⊗a=a并且 a ⊗ a = 0 a \otimes a = 0 a⊗a=0是因为其按位实现了模2加,如果我们设计一个加法运算其按位实现模3加即可到达上述效果。
我们使用数组char bit[32]
来保存一个特殊的32位整数,使其每个位可以是0、1或者2(普通的32位整数也可以表示成这种特殊的32位整数),我们可以通过按位实现模3加(即某个位的值到3时就将其置为0)来实现上述提到的运算
⊕
\oplus
⊕
bit num bit
00 0 (00 + 0) % 3
00 1 (00 + 1) % 3
00 + 0 = (00 + 0) % 3
... ... ...
00 1 (00 + 1) % 3
00 0 (00 + 0) % 3
代码
class Solution {
public:
int singleNumber(vector<int>& nums) {
char bit[32] = {0};
for(unsigned int n : nums) {
int p = 0;
while(n != 0) {
// 按位加
if (n & 0x1) {
bit[p]++;
// 每个位执行模3加
bit[p] %= 3;
}
p++;
n >>= 1;
}
}
int r = 0;
// 将特殊32位整数转换为普通32位整数
for(int i=0; i<32; i++) {
int c = 0x1 << i;
r += bit[i] * c;
}
return r;
}
};