标签:c style class blog code java
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?
都出现两次的好说,把所有的异或起来,结果就是,但是3次的怎么做
首先想到了三进制,出现3次的就忽略,但是以什么为基准统计次数呢?根据网上提示的思路,可以记录正数二进制形式哪些位为1。int型为4字节,即32位,因此创建一个大小为32的数组count用于计数,count[i]表示在第i位出现1的次数再模除3,若某个数出现3次,例如5,二进制位101,即第1位和第3位出现了1,当读到第一个5时,为第一位和第三位贡献一次1,当读到第二个时,贡献第二次,读到第三个5时,贡献第三次,模除以后相当于0次,相当于忽略掉出现3次的数,因此count数组上最后哪些位大于0,就是没有出现3次的那个数哪些位为1,再构造这个数即可,代码如下:
1 public int singleNumber(int[] A) { 2 int count[] = new int[32]; 3 for (int i = 0; i < A.length; i++) { 4 for (int j = 0; j < 32; j++) { 5 count[j] += (A[i] >> j) & 1; 6 count[j] %= 3; 7 } 8 } 9 int result = 0; 10 for (int i = 0; i < 32; i++) { 11 result += (count[i] << i); 12 } 13 return result; 14 }
上述代码对应于出现次数不是3次的那个数只出现了一次,若要适应可以出现一次或两次的情况,将result += (count[i] << i)改成result += ((count[i] + 1) / 2 << i)即可。
对于出现次数不是3次的那个数只出现了一次的情况,有一种更简单的做法,还是上面的思路,只是简化做法,不需要新开辟一个32个元素的数组。
////////////////////////////////////////////////////////////////////////////////下面有部分是转载的////////////////////////////////////////////////////////////////////////////////
转自http://www.cnblogs.com/x1957/p/3373994.html
用one 记录到当前处理的元素为止,二进制1 出现“1 次”(mod 3 之后的1)的有哪些二进制位;用two 记录到当前计算的变量为止,二进制1 出现“2 次”(mod 3 之后的2)的有哪些二进制位。当one 和two 中的某一位同时为1 时表示该二进制位上1 出现了3 次,此时需要清零。即用二进制模拟三进制运算。最终one 记录的是最终结果。
1 public int singleNumber(int[] A) { 2 int one = 0, two = 0, three = 0; 3 for (int i = 0; i < A.length; ++i) { 4 two |= (one & A[i]); 5 one ^= A[i]; 6 three = ~(one & two); 7 one &= three; 8 two &= three; 9 } 10 return one; 11 }
代码的主要部分就是for循环里的5行,下面逐行分析一下:
two |= (one & A[i]):one中记录的是计算到A[i-1]为止哪些位1出现1次,two记录的是计算到A[i-1]为止哪些位1出现两次,one&A[i]可以得到计算到A[i]为止哪些位上1出现两次,与two取或操作可以得到计算到A[i]为止哪些位1出现两次。因为这些位中有在A[i-1]的时候已经出现了两次,然后A[i]上又出现1次,已经到3次了,需要更新,这一步留到后面做。
one ^= A[i]:取异或,得到计算到A[i]为止哪些位1出现多余1次,即出现1次或3次,出现3次的情况需要更新,这一步留到后面做
three = ~(one & two):计算哪些位出现了3次
one &= three:即将上面one ^= A[i]这行出现3次的那部分更新掉
two &= three:即将two |= (one & A[i])这行出现超过2次的那部分更新掉。
最后one的结果就是只出现一次的数。
上述代码对应于出现次数不是3次的那个数只出现了一次,若要适应可以出现一次或两次的情况,将return one改成return one|two即可。
Single Number II,布布扣,bubuko.com
标签:c style class blog code java
原文地址:http://www.cnblogs.com/apoptoxin/p/3770415.html