Leetcode 137. Single Number II

来源:互联网 发布:网络实名制 弊端 编辑:程序博客网 时间:2024/06/06 13:12

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


解法:

有个很好理解的解法,因为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中出现三次的位。


0 0
原创粉丝点击