137. Single Number II

题目:

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?

 

Hide Tags
 Bit Manipulation
 

链接:http://leetcode.com/problems/single-number-ii/

题解:

主要参考了leetcode discussion以及daijinqiao的博文。

位运算,使用二进制模拟三进制。twos记录至当前变量为止,1出现2次的digit,ones记录至当前变量为止,1出现1次的digits, 所以ones & twos统计至当前变量为止含有3个1出现的digits, xthrees是对one & twos取反,之后与ones和twos分别作按位与运算,表示清零出现3次1的情况digit。最后返回的ones就是全数组中每个bit位只出现1次的数字。

扩展情况是假如每个数出现3次,只有一个数出现两次,那么返回twos就是结果。

 

Time Complexity - O(n), Space Complexity - O(1)

public class Solution {
    public int singleNumber(int[] nums) {
        if(nums == null || nums.length == 0)
            return 0;
        int ones = 0, twos = 0, xthrees = 0;
        
        for(int i = 0; i < nums.length; i ++){
            twos |= (ones & nums[i]);
            ones ^= nums[i];
            xthrees = ~(ones & twos);
            ones &= xthrees;
            twos &= xthrees;
        }
        
        return ones;
    }
}

 

还有一种方法是建立一个32位的array,把所有数组中数字的每bit位值加起来,再模3,最后剩下的就是只出现一次的数字。其实也算constant extra space和linear time。

Time Complexity - O(n), Space Complexity - O(1)。

public class Solution {
    public int singleNumber(int[] nums) {
        if(nums == null || nums.length == 0)
            return 0;
        int[] count = new int[32];
        int result = 0;
        
        for(int i = 0; i < 32; i++){
            for(int j = 0; j < nums.length; j++){
               if(((nums[j] >> i) & 1) > 0)           //check if the ith bit of  the current number is 1
                    count[i]++;
            }
            result |= (count[i] % 3) << i;       // equals to    count[i] %= 3;   result += count[i] << i;
        }
        
        return result;
    }
}

 

Update:

有关bit manipulation, 还需要多看一看<Hacker's Delight>以及Bit Twiddling Hacks -  https://graphics.stanford.edu/~seander/bithacks.html

public class Solution {
    public int singleNumber(int[] nums) {
        if(nums == null || nums.length == 0)
            return 0;
        int ones = 0, twos = 0, xThrees = 0;
        
        for(int i = 0; i < nums.length; i++) {
            twos |= (ones & nums[i]);     //first calculate twos, based one ones
            ones ^= nums[i];              //then update ones
            xThrees = ~(ones | twos);     //threes is counter of ones and twos
            ones &= xThrees;              //use xThrees to clear some digits of ones
            twos &= xThrees;              //use xThrees to clear some digits of twos
        }
        
        return ones;
    }
}

 

另一种方法的update,  

public class Solution {
    public int singleNumber(int[] nums) {
        if(nums == null || nums.length == 0)
            return 0;
        int[] bits = new int[32];                   //bit counter
        int res = 0;
        
        for(int i = 0; i < 32; i++) {
            for(int j = 0; j < nums.length; j++) 
                bits[i] += (nums[j] >> i) & 1;     //add up ith digit of all numbers
            bits[i] %= 3;                          //mod the sum by 3
            res += bits[i] << i;                   //add this digit to final result - the single number
        }
        
        return res;
    }
}

 

二刷:

Java:

三变量清零

public class Solution {
    public int singleNumber(int[] nums) {
        if (nums == null || nums.length == 0) return 0;
        int ones = 0, twos = 0, xThrees = 0;
        for (int num : nums) {
            twos |= (ones & num);
            ones ^= num;
            xThrees = ~(ones & twos);
            ones &= xThrees;
            twos &= xThrees;
        }
        return ones;
    }
}

 

开int[32] 数组清零, 把数组读取放在外循环速度反而比放在内循环慢,不知道是为什么

public class Solution {
    public int singleNumber(int[] nums) {
        if (nums == null || nums.length == 0) return 0;
        int[] bitmap = new int[32];
        for (int num : nums) {
            for (int i = 0; i < 32; i++) {
                bitmap[i] += (num >> i) & 1;
            }
        }
        int res = 0;
        for (int i = 0; i < 32; i++) res += ((bitmap[i] % 3) << i);
        return res;
    }
}

 

 

 

Reference:

https://leetcode.com/discuss/857/constant-space-solution 

http://www.cnblogs.com/daijinqiao/p/3352893.html

http://blog.csdn.net/a775700879/article/details/11393885

位运算:(胡乱丢一些link,以后再看)

http://graphics.stanford.edu/~seander/bithacks.html

http://bits.stephan-brumme.com/null.html

http://en.wikipedia.org/wiki/Bitwise_operation

http://www.cnblogs.com/foohack/p/3772910.html

http://blog.csdn.net/morewindows/article/details/7354571

http://www.matrix67.com/blog/archives/263

http://blog.csdn.net/zmazon/article/details/8262185

http://bisqwit.iki.fi/story/howto/bitmath/

https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=%E4%BD%8D%E8%BF%90%E7%AE%97+%E4%B9%A6%E7%B1%8D&start=20

http://www.cppblog.com/biao/archive/2012/03/20/168357.html

http://www.zhihu.com/question/27158924

http://bisqwit.iki.fi/story/howto/bitmath/

http://www.quora.com/Are-there-any-good-bit-manipulation-tutorials-for-C-C++

https://leetcode.com/discuss/9763/accepted-proper-explaination-does-anyone-have-better-idea 

https://leetcode.com/discuss/6632/challenge-me-thx

https://leetcode.com/discuss/44345/java-bit-manipulation-solution

https://leetcode.com/discuss/43377/the-simplest-solution-ever-with-clear-explanation

https://leetcode.com/discuss/31595/detailed-explanation-generalization-bitwise-operation-numbers

https://leetcode.com/discuss/54970/an-general-way-to-handle-all-this-sort-of-questions

 

posted @ 2015-04-19 11:15  YRB  阅读(488)  评论(0编辑  收藏  举报