题目如下:一个全是32位整数的大数组,除了其中一个数字出现2次外,其余的数字都出现了3次。如何找出那个只出现了两次的数字?
参考:http://blog.csdn.net/Dinosoft/article/details/6443354
def special(lst): ones = 0 twos = 0 for x in lst: twos |= ones & x ones ^= x not_threes = ~( ones & twos ) ones &= not_threes twos &= not_threes return twos
其中ones记录了所有出现了(模3余1)次的bit,twos记录的是余2的。not_threes是当一个bit出现第3次的时候,bit位置0
在代码中,ones ^= x 执行后,如果ones的一个bit等于1,说明这个bit=1的情况出现了1, 3, 5...奇数次,在本题中只会取1, 3。
twos |= ones & x ,其中的ones & x确定了这一轮会得到的余2的bit(从ones中加x来到twos),而原来的twos中有的bit会变成余0(加上x中对应的bit离开twos),有的保持余2(x中没对应的bit),所以先统统算进是余2的部分。
ones ^= x得到的是加上x后出现1或3次的bit。
(ones & twos)得到的就是 (出现1或3次的bit) & (余2或余0的bit) = 出现3次的bit
~(ones & twos),作为掩码置0。
另一种写法
(one, two) = (0, 0) for num in nums: one = (one ^ num) & ~two two = (two ^ num) & ~one print two