您的位置:首页 > 其它

寻找丢失的数字(一)

2012-04-24 14:56 134 查看
这是一个有趣的面试题。

有一个袋子,里面放有1, 2, 3, ... , 100, 共100个整数,且每个数字只出现一次。现在由于袋子破了个洞,造成其中一个数字丢失了。请找出丢失的数字。很容易想到的方法是:我们可以用减法,1 + 2 + ... + 100的和减去袋子中所有数的和,其差就是丢失的那个数字。1 + 2 + ... + 100

可以由等差数列公式100 * (1 + 100) / 2 = 5050算出,我们只需要遍历一次袋子中的数字即可。

把这道题推广到一般情况:设 π 是{1, 2, ... , n}的一个全排列,π-1 是 π 中丢失了一个数字后的序列。找出序列 π-1 中缺失的数字。

当 n 比较小时,我们仍可以用上面的方法,但是当 n 很大时,上面的方法就会有溢出的问题。虽然我们可以合理安排加减法的顺序以避

免溢出,但实际上我们有更巧妙的方法来解决这类问题。

回忆异或(XOR)运算的性质:

a XOR a = 0 a XOR 0 = a我们从1异或到100,然后再和袋子里的数逐个异或,因为一个数与自身异或,结果是0,所以异或最后的结果就是丢失的数字。

Python 代码:

def find_missing_1_number(sequence, n):
""" returns the missing number of sequence, which is supposed to be
a permutation of {1,..,n} with one number missing.
"""
x = n
for i in xrange(1, n):
x ^= i
for e in sequence:
x ^= e
return x



扩展问题一:如果其中两个数字丢失了,怎么办?显然,用上述方法不能同时求出两个数。这是否意味着这种巧妙的方法不再适用了?让我们先看一下,用上述方法求出的是什么。

设丢失的两个数字为a和b,那么上述方法求出的结果就是 a XOR b。我们能否利用这个结果呢?答案是YES。因为a != b,那么

a 和 b 的二进制表示形式中一定至少有一位相异。我们可以根据该位把数字分成两组,该位为0的一组和该位为1的一组。两组分别

用上述方法异或,最后两组异或的结果就是 a 和 b。

Python 代码:

def find_missing_2_numbers(sequence, n):
""" returns the missing two numbers of sequence, which is supposed
to be a permutation of {1,..,n} with two numbers missing.
"""
x = n
for i in xrange(1, n):
x ^= i
for e in sequence:
x ^= e
diff = x & (-x) # isolates the rightmost 1-bit
a, b = 0, 0
for i in xrange(1, n + 1):
if i & diff:
a ^= i
else:
b ^= i
for e in sequence:
if e & diff:
a ^= e
else:
b ^= e
return a, b注意在上面的方法中,我们要扫描两遍这个序列。虽然复杂度仍是O(n),但是在某些特殊情况下,我们可能没有第二次扫描的机会。

那么,能否只扫描一遍就算出结果呢?请看寻找丢失的数字(二)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: