码迷,mamicode.com
首页 > 其他好文 > 详细

Single Number II

时间:2014-06-07 07:44:19      阅读:192      评论:0      收藏:0      [点我收藏+]

标签: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,再构造这个数即可,代码如下:

bubuko.com,布布扣
 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     }
bubuko.com,布布扣

上述代码对应于出现次数不是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 记录的是最终结果。

bubuko.com,布布扣
 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     }
bubuko.com,布布扣

代码的主要部分就是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

Single Number II

标签:c   style   class   blog   code   java   

原文地址:http://www.cnblogs.com/apoptoxin/p/3770415.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!