跟上一个题目很类似,只不过相同的数字出现3次,刚开始也是没有想法,想了很多关于位运算的相关的东西,可是3次始终没办法弄。
于是手欠搜了下答案。。。。。。
此题还是一个很好的题目,对于位运算的操作来说,或许能学到很多东西。
解法1:
int 为32位,统计所有32位,每个位1出现的次数,然后模3,若结果还为1,代表这个单的数这位为1,以此类推。
时间:O(32*N),这是一个通用的解法,如果把出现3次改为 k 次,那么只需模k就行了。
class Solution {
public:
int singleNumber(int A[], int n) {
int bitNum[32]={0};
int res;
for(int i=0;i<32;i++){
for(int j=0;j<n;j++){
bitNum[i]+=(A[j]>>i)&1;
}
res|=(bitNum[i]%3)<<i;
}
return res;
}
};
解法2:(还需理解)
需要一个表示相应位出现次数模3余1的变量,一个表示相应位出现次数模3余2的变量。
代码也是炫酷。
public class Solution {
public int singleNumber(int[] A) {
// Note: The Solution object is instantiated only once and is reused by each test case.
int one = 0;
int two = 0;
for(int i=0; i<A.length; i++){
int tmp;
tmp = ((one ^ A[i]) & (~two));
two = ((one & A[i]) | (two & (~A[i])));
one = tmp;
}
return one;
}
}
另一种代码形式:(参考: http://blog.csdn.net/jiadebin890724/article/details/23306837)
这是一个更快一些的解法,利用三个变量分别保存各个二进制位上 1 出现一次、两次、三次的分布情况,最后只需返回变量一就行了。
class Solution {
public:
int singleNumber(int A[], int n) {
int one=0, two=0, three=0;
for(int i=0; i<n; i++){
two |= one&A[i];
one^=A[i];
//cout<<one<<endl;
three=one&two;
one&= ~three;
two&= ~three;
}
return one;
}
};