寻找丢失的数字(二)

如果你还没有看过上一篇文章,请先移步看问题描述。

扩展问题二:至多扫描一遍序列,求出丢失的两个数字。  

不管用什么方法,可以肯定的是我们至少需要扫描一遍序列。

因为只能扫描一遍,所以先求出 a XOR b,再根据结果分类的方法就不适用了。

既然我们不能根据某一位分类,那我们能否对所有位进行分类呢?比如,int是32位,我们可以对每一位都分成两类分别异或。

我们还要记录每一位上1出现的次数,实际上,只需要记录1出现奇数次还是偶数次就够了。 

如果某一位上1出现奇数次,那么我们就知道 a 和 b 在此位上的比特不同。从而利用前面分类异或的结果就直接得出答案。

Python 代码:

def find_missing_2_numbers_v2(sequence, n):
     """  returns the missing two numbers of sequence, which is supposed
    to be a permutation of {1,..,n} with two numbers missing.
    An one-pass algorithm.
    
"""
    xors = [[0  for i  in xrange(2)]  for j  in xrange(32)]
    counts = [0  for i  in xrange(32)]
     for i  in xrange(1, n + 1):
         for k  in xrange(32):
            t = 1 & (i >> k)
            xors[k][t] ^= i
            counts[k] ^= t
     for e  in sequence:
         for k  in xrange(32):
            t = 1 & (e >> k)
            xors[k][t] ^= e
            counts[k] ^= t
    a, b = 0, 0
     for k  in xrange(32):
         if counts[k]:
            a, b = xors[k][0], xors[k][1]
             break

    return a, b 

 

扩展问题三:如果有三个数字丢失了呢?

其实上面的方法稍加修改就可以解决此问,具体实现留给读者。有道类似题目http://yzfy.org/dis/listpost.php?tid=1009 可以用来测试你的算法~

转载于:https://www.cnblogs.com/shilcare/archive/2012/04/24/2468336.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值