您的位置:首页 > 其它

LeetCode | Single Number II(单个数字II)

2014-08-16 17:35 387 查看
Given an array of integers, every element appears three times
except for one. Find that single one.

Note:

Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

题目解析:

除了一个数只出现一次以外,其他元素都出现了三次。

这道题目比较难,比较普遍的方式是,建立哈希表,统计每一个元素出现的次数,然后再返回个数为1的元素。

但是题目中要求,只能用常量空间,不能这样做。

方案一:

类似哈希,我们可以通过记录元素的某一位的个数,既然都出现三次,则其对应的位为3的倍数。求出以后,对所有为mod 3就行了。得到的是最后要找的数据。

class Solution {
public:
int singleNumber(int A[], int n) {
int bitnum[32]={0};
int res=0;
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;
}
};


这里是以位为主循环,一次求所有数据的某一位的个数。然后对res或运算。

时间:O(32*N),这是一个通用的解法,如果把出现3次改为 k 次,那么只需模k就行了。

方案二:

利用三个变量one,two,three。

one的位表示只出现了一次,two的位表示出现了两次,那么three = two & one就表示为1的位已经出现了三次。那么最后将one和two中对应的位清零。

当然函数进入的时候,先通过two |= one & a[i]计算所有出现两次的位。结合上面说的one中的位值出现了1次,和a[i]相与后,得到了当前已经出现了两次的位。当然由于two是或的,可能已经有包含的1,则该位就出现了四次。先往下走。

然后是one = one ^ a[i];由于已经把都为1的值保存在two中,这里也就清掉了为one和a[i]中都为1的位。但如果one的第k位为0,a[i]的第k位也为0,会将one置为1。这也无妨当出现a[i]为3个的时候,会将该k位清除的。

流程:

1、更新two |= one & a[i]

2、更新one ^= a[i]

3、更新three = one & two

4、清除one和two已经满足3个的位:one &= ~three;two &= ~three

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;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: