数组中三个只出现一次的数字1

        一个数组中有三个数字a、b、c只出现一次,其他数字都出现了两次。请找出三个只出现一次的数字。

     本题是一题是一道比经典的面试题了,也有不少博客给出了相应的解法:个人觉得比较经典解法有以下两个(直接贴出链接吧):

       http://blog.csdn.net/wypblog/article/details/8032898

      http://zhedahht.blog.163.com/blog/static/25411174201283084246412/

      但是晚上详细看了第二种解法,也就是何海涛

博主给的那个,个人觉得他的推导过程有些问题,前面部分的推导就直接搬过来(这里用不同的字体标出,不知道怎么引用):   

        如果我们把数组中所有数字都异或起来,那最终的结果(记为x)就是a、b、c三个数字的异或结果(x=a^b^c)。其他出现了两次的数字在异或运算中相互抵消了。

我们可以证明异或的结果x不可能是a、b、c三个互不相同的数字中的任何一个。我们用反证法证明。假设x等于a、b、c中的某一个。比如x等于a,也就是a=a^b^c。因此b^c等于0,即b等于c。这与a、b、c是三个互不相同的三个数相矛盾。

     由于x与a、b、c都各不相同,因此x^a、x^b、x^c都不等于0。

我们定义一个函数f(n),它的结果是保留数字n的二进制表示中的最后一位1,而把其他所有位都变成0。比如十进制6表示成二进制是0110,因此f(6)的结果为2(二进制为0010)。f(x^a)、f(x^b)、f(x^c)的结果均不等于0。

接着我们考虑f(x^a)^f(x^b)^f(x^c)的结果。由于对于非0的n,f(n)的结果的二进制表示中只有一个数位是1,因此f(x^a)^f(x^b)^f(x^c)的结果肯定不为0。这是因为对于任意三个非零的数i、j、k,f(i)^f(j)的结果要么为0,要么结果的二进制结果中有两个1。不管是那种情况,f(i)^f(j)都不可能等于f(k),因为f(k)不等于0,并且结果的二进制中只有一位是1。

      于是f(x^a)^f(x^b)^f(x^c)的结果的二进制中至少有一位是1。假设最后一位是1的位是第m位。那么x^a、x^b、x^c的结果中,有一个或者三个数字的第m位是1。

     问题就在上面标为蓝色的部分,如果最后一位是1的位为m位,不能得出x^a、x^b、x^c的结果中有一个或者三个数字的第m位是1。举个反例:若 x^a、x^b、x^c分别为011、101、110 它们f(x^a)^f(x^b)^f(x^c)的结果为010,此时m为1(从0开始计数),但 011、101、110却有两个数字第1位是1。

    一下给出我的推导过程,不对的地方希望大家能够帮我指出来:

    f(x^a)^f(x^b)^f(x^c)的结果设为k,由于它的m位为1,所以x^a、x^b、x^c中至少有一个m位1。这个用反证法容易证明。因此x^a、x^b、x^c中有一个、两个、或三个的m位为1。

    (1)若x^a、x^b、x^c中三个m位都为1,原文证明了是不可能的。直接摘入如下:

       接下来我们证明x^a、x^b、x^c的三个结果第m位不可能都是1。还是用反证法证明。如果x^a、x^b、x^c的第m位都是1,那么a、b、c三个数字的第m位和x的第m位都相反,因此a、b、c三个数字的第m位相同。如果a、b、c三个数字的第m位都是0,x=a^b^c结果的第m位是0。由于x和a两个数字的第m位都是0,x^a结果的第m位应该是0。同理可以证明x^b、x^c第m位都是0。这与我们的假设矛盾。如果a、b、c三个数字的第m位都是1,x=a^b^c结果的第m位是1。由于x和a两个数字的第m位都是1,x^a结果的第m位应该是0。同理可以证明x^b、x^c第m位都是0。这还是与我们的假设矛盾。

(2)若x^a、x^b、x^c中只有1个m位为1。不妨设它为x^a,则x^b、x^c,m位都为0,由此可知x的m为与b、c相同,与a的m位相反。x的m为与b、c相同,则b、c的m位必然相同,因此b、c的m位异或后的结果必为0,又有x为a、b、c异或后的结果,则在b、c的m位相同的条件下a的m位必与x相同。这与题设产生结论相互矛盾。同理可证,m位为1的是x^b或x^c时。因此x^a、x^b、x^c中不可能只有1个m位为1

    综上所述,x^a、x^b、x^c中只可能为,有两个的结果m位为1,一个结果m位为0。因此我们知道a、b、c中有两个m位与x相反,一个的m位与x相同。由此便可从中先把那个相同的那个数,找出来,然后再去找其他两个。具体,明天写代码验证一下,后发上来。今天太晚了,先休息啦。


     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值