如果你还没有看过上一篇文章,请先移步看问题描述。
扩展问题二:至多扫描一遍序列,求出丢失的两个数字。
不管用什么方法,可以肯定的是我们至少需要扫描一遍序列。
因为只能扫描一遍,所以先求出 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
""" 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 可以用来测试你的算法~