题目:
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?
链接: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/
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