Single Number III
题意
给你一个数组,里面有且仅有两个数字出现一次,其他数字都出现两次。现在让你用O(n)的时间效率和O(1)的空间效率找出这两个只出现了一次的数字。
解法
我感觉做了这么多题,这道题目真的让我神清气爽,想法真的只能用一个字来形容,就是妙!
好了废话不多说,照搬下大牛的思路。
如果有两个数字不一样,那么说明它们的二进制表示肯定是至少有一位不同的。那么它俩亦或的结果的二进制表示中,1代表的就是它俩不同的位(亦或嘛,不同为1)。那么我们先找到最右边的那个1位,怎么找?记得树状数组那个神奇的lowbit公式吗?那就是找最低位的1,所以如果一个数为x,那么它的最低位的1就是x&(-x)。
因为这道题目中只有两个数字出现过一次,其他数字都是出现两次,那么按照亦或的定义,我们把数组中全部的数字亦或起来,得到的就是那两个只出现一次的数字的亦或值。接着就按照上述的找最右边的二进制位为1所代表的值,其他位都为0,假设这个值就为ssum。
接下去就很精妙了,我们开始遍历数组,假设数组数字为x,那么这个数组中的值就可以被分为两个集合,分别为 (x&ssum > 0) 以及 (x&ssum == 0)的。为什么可以这么分?首先我们先看除了那两个数字以外其它的数字,我们发现,两个相同的数字肯定是出现在同一个集合中的,这不用说。对于那两个数字来说,一个肯定是在>0 的集合中,一个肯定是在=0的集合中,因为刚才我们说明了,ssum代表的是两个数字亦或值最右边的那个1所代表的值,这个1就是那两个数字的至少不同的那一位,所以肯定一个为0,一个为>0!
这就将数字分成了两个集合,假如原数组是[1, 2, 1, 3, 2, 5],那么这两个集合分别为:
> 0: 2,2,3
= 0:1,1,5
得到这两个集合后咋办?亦或啊!把这两个单独出现的数字分开以后一亦或,就可以得到答案了。。
太神!
代码
|
|