在一个长度为n的整形数组a里,除了三个数字只出现一次外,其他的数字都出现了2次。请写程序输出任意一个只出现一次的数字

在一个长度为n的整形数组a里,除了三个数字只出现一次外,其他的数字都出现了2次。请写程序输出任意一个只出现一次的数字,程序时间和空间复杂度越小越好。
例如: a = {1,3,7,9,5,9,4,3,6,1,7},输出4或5或6
算法流程:
(1). f(x) = x&(-x)   ----->该函数可以得出x从右边开始出现1的位置,比如 f(0x1100) = 0x0100
(2).  x = a^b^c
(3).   flag = f(x^a)^f(x^b)^f(x^c) 结果必有一位是1,因为flag不可能为0 ,因此flag在某一位上一定为1
       证明:   f(x^a),f(x^b),f(x^c)分别表示 x^a, x^b, x^c的右边第一个1的位置,并且
                 x^a = b^c, x^b=a^c,x^c=a^b
                 假设flag的值为0,那么 f(x^a),f(x^b),f(x^c)都为0,即 x^a, x^b, x^c为0,那么a=b=c矛盾
(4). f(x^a)^f(x^b)^f(x^c)的第m位为1,则f(x^a), f(x^b), f(x^c)必有1个或者3个第m位为1,因为只能是  0^0^1=1或者1^1^1=1
(5). x^a, x^b, x^c只有一个第m位为1
      证明(5) 由于(4)得出, f(x^a), f(x^b), f(x^c) 必有1个或者3个第m位为1,(结论1)因此 x^a, x^b, x^c的第m位最多是1个为1或者三个为1。因为f(x)表示x的右边第一个为1的位置,那么f(x)值的第m位为1(f(x)中只能有一个1),也就表示x的第m位也为1.因此f(x)为1的位置和x为1的位置是对应的。假设 x^a, x^b, x^c 有三个在m位上为1。
      1> 如果 x(m) =1 --------->x(m)表示x的m位,下同。
           那么必有:a(m) = 0,b(m)=0, c(m)=0.
                 并且x(m) = a(m)^b(m)^c(m) = 0 矛盾。
      2>如果 x(m) = 0:
           那么必有:a(m) = 1,b(m)= 1,c(m) = 1
                 并且x(m) = a(m)^b(m)^c(m) = 1 矛盾。
      综上所述, x^a, x^b, x^c 有三个在m位上为1的假设是不成立的。因此只能有一个。
(6)flag = f ( f(x^a)^f(x^b)^f(x^c))

(7)如果f(x^i) = flag的数都在一组里面,并且包含了所求的值,最后对这组值求异或即得结果。

代码如下:

int f(int x)
{
    return x&(-x);
}
int find(int [] datas)
{
     int len=datas.length;
     int x = 0;
     for(int i=0;i<len;i++){
          x ^= datas[i];
     }
     int flag =  0;
     for(int i=0;i<len;i++){
          flag ^= f(x^datas[i]);
     }
     int b=0;
     for(int i=0;i<len;i++){
         if(f(x^datas[i]) == f(flag))
               b ^= datas[i];
     }
     return b;
}
参考文章: 数组中N(n=1,2,3)个只出现一次的数字

对文章中的算法进行证明,并且还该掉了一处错误的地方(如果改得不对,还望指正),然后使用java实现算法,代码是参考hackbuteer1的2013年小米校园招聘笔试题

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值