原题链接在这里:https://leetcode.com/problems/single-number-ii/
题目:
Given a non-empty array of integers, every element appears three times except for one, which appears exactly once. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
Example 1:
Input: [2,2,3,2] Output: 3
Example 2:
Input: [0,1,0,1,0,1,99] Output: 99
题解:
这道题的关键就是要求no extra memory space. 所以就用到了bit manipulation.
用one记录到当前计算的变量为止,二进制1出现"1次"(mod 3 之后的 1)的数位.
用two记录到当前计算的变量为止,二进制1出现"2次"(mod 3 之后的 2)的数位. update by ^= (once already appeared, num appeared again).
当one和two中的某一位同时为1时表示二进制1出现3次,此时需要清零.
即用二进制模拟三进制计算, 最终ones记录的是最终结果.
Time Complexity: O(n).
Space: O(1).
AC Java:
1 class Solution { 2 public int singleNumber(int[] nums) { 3 int one = 0, two = 0; 4 for(int num : nums){ 5 two ^= one & num; 6 one ^= num; 7 int notThree = ~(one & two); 8 two &= notThree; 9 one &= notThree; 10 } 11 12 return one; 13 } 14 }
另一方法是维护一个32位的数组,因为int 都是32位的,外层loop是对应每一位,内层loop是算所有的数在这一位上出现次数的和。
Mod 3 后剩下的就是那个只出现了一次的数。与Single Number类似.
Note:1. Check if current bit is 1 using:
nums[j] >> i & 1
但要注意的是bit operator: >>, & 都比 == operator 运算级别低,所以要加括号.
2. 给了一个array代表2进制的数,转化成10进制的数就是用
res += bitCounter[i]<<i
Time Complexity: O(n). Space: O(1).
AC Java:
1 class Solution { 2 public int singleNumber(int[] nums) { 3 int res = 0; 4 5 int [] bitCount = new int[32]; 6 for(int i = 0; i<32; i++){ 7 for(int j = 0; j<nums.length; j++){ 8 bitCount[i] = (bitCount[i] + (nums[j]>>i&1))%3; 9 } 10 } 11 12 for(int i = 0; i<32; i++){ 13 res += bitCount[i]<<i; 14 } 15 16 return res; 17 } 18 }