LeetCode: Single Number II

来源:互联网 发布:手机淘宝掌柜热卖在哪 编辑:程序博客网 时间:2024/06/05 05:06

人类解法我就不说了,最基础的hashtable计数,或者按位相加模3等等。现在主要看这个solution,代码来自stackoverflow, 但是那个解释我还是觉得不到位。。。


    int singleNumber(int A[], int n) {        int one = 0;        int two = 0;        int not_three = 0;        for(int i=0; i<n; i++){            two |= one&A[i];            one ^= A[i];            not_three = ~(one&two);            one &= not_three;            two &= not_three;        }        return one;    }

代码很简洁就是看起来头大。简而言之,这个solution仍然是对每个bit进行计数,只不过是在原地计数,省空间省时间。

复习下最基本的异或操作:1^0=1, 0^1=1, 1^1=0, 0^0=0. 有没有发现,异或不仅可以a^a=0, 同时可以方便的对每个bit上的1进行计数。

变量one就是通过异或操作不断对每个元素每个bit上的1进行计数。如果上面代码没有not_three相关的操作,那么one中某bit上如果为1的话,表明数组中元素该bit上的1出现过奇数次。对于这道题这点信息是不够的,后面会继续解释。

变量two:如果数组中元素的某个bit上1出现过一次,那么one中的相应bit肯定会置1。当该bit第二次出现1时(即1出现了2次),那么two的对应bit会被置1记录该信息。也就是说,当某个bit上的1累加了两次时,one中对应的bit毫无疑问会置0,而two中对应的bit会被置1。

变量not_three:当数组中元素的某个bit上1出现第三次的时候,two对应bit上的1不变,而one对应bit会被置1。那么我们就有了出现三次1的bit位信息,即one&two。出现三次的1是题目要求过滤掉的,故有了one&=not_three; two&=not_three。

就整个数组而言,除了那个single number,每个bit上的1都会出现3n次从而被如上步骤过滤掉,余下的bit为1的信息,即one就是所查找的single number。


0 0