LeetCode(137)Single NumberII

题目如下:

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?

分析如下:

借助上一题的惯性思维,考虑用异或之类的位运算方式来解决,但是基本上想不出答案。网上搜了一下,看到一个绝妙的做法。
输入是int型数组,所以可以用32位来表达输入数组的元素。
假设输入中没有single number,那么输入中的每个数字都重复出现了数字,也就是说,对这32位中的每一位i而言,所有的输入加起来之后,第i位一定是3的倍数。
现在增加了single number,那么对这32位中的每一位做相同的处理,也就是说,逐位把所有的输入加起来,并且看看第i位的和除以3的余数,这个余数就是single numer在第i位的取值。这样就得到了single number在第i位的取值。这等价于一个模拟的二进制,接着只需要把这个模拟的二进制转化为十进制输出即可。
为了完成上面的过程,需要使用一个数组 int a[ 32 ]来模拟位运算。
可以看出来,这个做法对于功力的要求非常高,需要看到数字的时候,眼前展现的是数字背后的二进制组成,要不然很难想到可以逐位去处理。
另外,这个做法可以扩展,如果有一堆输入,其中1个数字出现了1次,剩下的数字出现了K次,这样的问题全部可以使用这样的办法来做。

我的代码:
其实是从mitbbs上偷来的。。。

//80ms过大集合
class Solution {
public:
    int singleNumber(int A[], int n) {
        int count[32]={0};
        int result=0;
        for(int i=0;i<32;i++){
            for(int j=0;j<n;j++){
                count[i]+=((A[j]>>i)&1); //首先把输入数字的第i位加起来。
                count[i]=count[i]%3; //然后求它们除以3的余数。
            }
            result|=(count[i]<<i);//把二进制表示的结果转化为十进制表示的结果
        }
        return result;
    }
};

参考资料:

(1) http://www.mitbbs.com/article_t/JobHunting/32547143.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值