lintcode83- Single Number II- midium

Given 3*n + 1 numbers, every numbers occurs triple times except one, find it.
Given [1,1,2,3,3,3,2,2,4,1] return 4
 
法1:加和掩码提取位,模三,加到结果里。int 数据共有32位,针对其中具体某一位,可以用掩码(>>操作和 &1操作)把所有数字的这一位都加起来。针对重复3次的数字,他们加的和%3必定为0(0*3 %3 ==0, 1*3 %3 ==0),那么所有的和%3得到的必定就是寻找的数在这一位上到底是1还是0了。把这一位<<,并且加到res变量返回即可。
 
public class Solution {
    /**
     * @param A : An integer array
     * @return : An integer 
     */
    public int singleNumberII(int[] A) {
        // write your code here
        int res = 0;
        for (int i = 0; i < 32; i++){
            int rsBit = 0;
            for (int idx = 0; idx < A.length; idx++){
                int bit = A[idx] >> i;
                bit &= 1;
                rsBit += bit;
            }
            rsBit %= 3;
            res += rsBit << i;
        }
        return res;
    }
}
法2:利用三个变量分别保存各个二进制位上 1 出现一次、两次、三次的分布情况,最后只需返回变量一。
1. 代码使得这三个变量表现形式是: 某数第一次出现- 100,某数第二次出现-010,某数第三次出现- 111(后续抹去变为001)。所以如果某个数是只出现一次(3n+1),它的特征位会被保留在ones中,如果某个数是出现正好两次(3n+2),它的特征位会被保留在twos中。
2. 小心一下循环里要先处理2再处理1。
3. |= 是想做赋一处理,&= 是想做归零处理。^= 是想做“突出奇数次特征位,抹平偶数次特征位”处理。
public class Solution {
    /**
     * @param A : An integer array
     * @return : An integer 
     */
    public int singleNumberII(int[] A) {
        // write your code here
        int ones = 0, twos = 0, threes = 0;
        
        for(int i = 0; i < A.length; i++){
            //某数第一次进来,ones twos threes  1 0 0
            //某数第二次进来,ones twos threes  0 1 0
            //某数第三次进来,ones twos threes先1 1 1, 后 0 0 1
            //某数第四次进来,ones twos threes  1 0 0
            //循环
            twos |= ones & A[i];
            ones ^= A[i];
            threes = ones & twos;
            //第三次来时抹去一二痕迹
            twos &= ~three;
            ones &= ~three;
        }
        
        return ones;
    }
}
原文地址:https://www.cnblogs.com/jasminemzy/p/7509782.html