Single Number II
最笨的方法就是计数,将每一个整数都看成一个长度位32的数组,然后统计32位中每一位出现1的次数。如果一个数出现3次,则其出现1的位肯定也是3次,这时如果某位出现4次,则意味着出现一次的数在该位也为1。通过分析所有的位,我们即可以找到这个出现一次的数。
class Solution {
public:
int singleNumber(vector<int>& nums) {
int res = 0;
for (int i = 0; i < 32; ++i) {
int sum = 0;
for (int j = 0; j < nums.size(); ++j) {
sum += (nums[j] >> i) & 1;
}
res |= (sum % 3) << i;
}
return res;
}
};
把数组中数字的每一位累加起来对3取余,剩下的结果就是那个单独数组该位上的数字,由于我们累加的过程都要对3取余,那么每一位上累加的过程就是0->1->2->0,换成二进制的表示为00->01->10->00,那么我们可以写出对应关系:
00 (+) 1 = 01
01 (+) 1 = 10
10 (+) 1 = 00 ( mod 3)
那么我们用ab来表示开始的状态,对于加1操作后,得到的新状态的ab的算法如下:
b = b xor r & ~a;
a = a xor r & ~b;
我们这里的ab就是上面的三种状态00,01,10的十位和各位,刚开始的时候,a和b都是0,当此时遇到数字1的时候,b更新为1,a更新为0,就是01的状态;再次遇到1的时候,b更新为0,a更新为1,就是10的状态;再次遇到1的时候,b更新为0,a更新为0,就是00的状态,相当于重置了;最后的结果保存在b中。
class Solution {
public:
int singleNumber(vector<int>& nums) {
int a = 0, b = 0;
for (int i = 0; i < nums.size(); ++i) {
b = (b ^ nums[i]) & ~a;
a = (a ^ nums[i]) & ~b;
}
return b;
}
};