Leetcode 137. Single Number II

题意:给定一个数组,已知这个数组中有一个数出现了一次,其它数都出现三次。找出这个数


解法:

有个很好理解的解法,因为int有32位,所以开一个数组bit[32],遍历32次,把每个位出现的次数分别存入数组中,最后bit[32]分别对3取模,得到的结果,只出现一次的数。

这个算法的时间复杂度为O(32*N),相当的高。

从别的地方you看到另一种解法,复杂度为O(N),乍一看看不懂,遂好好分析了一下:

class Solution {
public:
    int singleNumber(int A[], int n)
        int one,two,three;
        one=two=three=0;
        for(int i=0;i<n;i++)
        {//一定是出现3次,2次,1次这样的顺序,如果反过来的话,先更新了one的话,会影响到two和three的
            three =  two & A[i];//已经出现了两次,还出现了一次
            two = two | one & A[i];//出现了1次又出现了1次,在加上以前已经出现了2次的,为新的出现了2次的
            one = one | A[i];//出现了1次
            //将出现3次的其出现1次2次全部抹去
            one = one & ~three;
            two = two & ~three;
        }
         return one;
    }
};

代码是随便找的,大概思想就是,int占32位,于是用三个变量one,two,three,分别表示出现一次,出现两次,出现三次的 我们最后只要出现一次的,也就是one的值,就是数组中只出现一次的数。

那么,如何用one,two,three分别存储出现一次两次三次的位呢?

首先,one中存的是出现一次的,所以one&A[i]即得到这次出现两次的位(&代表one和A[i]都有,所以必然是出现了两次)

即two = one&A[i];

同理three = two&A[i];

但是这里要强调一下,three=two&A[i]是没错,但是,这是这次出现过的位

所以程序有几个步骤

1,计算出,这次出现三次的位

2,计算出,one|(这次出现一次的位),two|(这次出现两次的位)

3,剔除one中出现两次的位,two中出现三次的位。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值