题目:
Given an array of integers, every element appears twice except for one. Find that single one.
这题的标签是hash table和bit manipulation,首先想到bit manipulation的思路,由于一个整型数和自己的异或操作得到是全零,全零和任何整型异或都不会改变整型的位表示。所以将数组所有元素取异或操作即可。
class Solution {
public:
int singleNumber(int A[], int n) {
if(n<=0){
return 0;
}
int res=0;
for(int i=0;i<n;++i){
res^=A[i];
}
return res;
}
};
然后是一个变题:
Given an array of integers, every element appears three times except for one. Find that single one.
注意到,这次重复的元素都出现了三次,所以上面简单的XOR做法就没用了。
对于数组里的所有数,其1~32位的所有‘1’的个数只能是3n或3n+1(n>=0)。对于每一位,我们用一个模为3的计数器,(B1,B0),对于(B1,B0):
(1,1)表示此位上已经出现了3次‘1’
(1,0)表示此位上已经出现了2次‘1’
(0,1)表示此位上已经出现了1次‘1’
(0,0)表示此位上已经出现了0次‘1’
那么对于32位,我们可以用b1,b0两个整型数来分布表示所有32位上的B1和B0,同时我们用变量reset来表示在每一位是否‘1’已经出现了3的整数倍次,如果是则设置reset此位为1,然后将b1,b0对应位重置为0。这样遍历完整个数列,b1必然为全0向量,b0则是那个要找的数。
将b0,b1,reset都初始化为0,b0的更新很显然为b0^=A[i],而B1设置为1只当B0为1且A[i]对应为为1。同时当B0,B1同时为1时要重置。
代码如下:
class Solution {
public:
int singleNumber(int A[], int n) {
int b0=0,b1=0,reset=0;
if(n<=0){
return 0;
}
for(int i=0;i<n;++i){
b1|=b0&A[i];
b0=b0^A[i];
reset=b0&b1;
b0=b0^reset;
b1=b1^reset;
}
return b0;
}
};
第二题用到了更加巧妙地位操作方法,如果说不是3个重复,而是4个重复的,5个重复的,我们同样可以用这种方法,用模4计数器或者模5计数器。