给定从1到2 ^ 32-1的数字,缺少一个。如何最佳地找到缺失的数字?

时间:2009-05-05 11:01:49

标签: algorithm

您将获得2 ^ 32-2个唯一数字,范围从1到2 ^ 32-1。将所有数字都放入内存是不可能的(因此排序不是一种选择)。系统会要求您找到丢失的号码。解决这个问题的最佳方法是什么?


假设您不能使用大整数并且仅限于32位整数。

int通过标准传入。

5 个答案:

答案 0 :(得分:32)

主要编辑:相信我会让事情变得更加艰难。

所有这些都是XOR。

我在这里假设数字是1到2 32 - 1 包含。这应该使用一个32位的额外内存位置。

编辑:我以为我可以逃脱魔法。好吧。

说明:

对于那些知道汉明码如何工作的人来说,这是一样的想法。

基本上,对于从0到2 n - 1的所有数字,在数字的每个位位置上恰好有2个(n - 1) 1。因此,对所有这些数字进行xoring实际上应该为0.但是,由于缺少一个数字,该特定列将给出一个,因为在该位位置存在奇数个数。

注意:虽然我个人更喜欢使用**运算符进行求幂,但我已经将我改为^,因为这就是OP所使用的。不要混淆^ for xor。

答案 1 :(得分:12)

使用您最喜欢的大整数库添加您放弃的所有数字,并从sum of arithmetic progression formula

获得的1到2 ^ 32-1之间的所有数字之和中减去该总数

答案 2 :(得分:4)

使用按位运算符XOR。以下是JavaScript中的示例:

var numbers = [6, 2, 4, 5, 7, 1]; //2^3 exclude one, starting from 1
var result = 0;

//xor all values in numbers
for (var i = 0, l = numbers.length; i < l; i++) {
    result ^= numbers[i]; 
}

console.log(result); //3

numbers[0] = 3; //replace 6 with 3
//same as above in functional style
result = numbers.reduce(function (previousValue, currentValue, index, array) {return currentValue ^= previousValue;});

console.log(result); //6

在C#中也一样:

int[] numbers = {3, 2, 4, 5, 7, 1};

int missing = numbers.Aggregate((result, next) => result ^ next);

Console.WriteLine(missing);

答案 3 :(得分:1)

假设你可以获得Size(),你可以使用一些二进制方法。选择数字组n,其中n < 2 ^ 32 -2 / 2.然后得到一个计数。失踪方应报告较低的数量。迭代地完成这个过程然后你会得到答案

答案 4 :(得分:0)

如果您没有XOR,则当然可以使用普通的“未经检查的”总和来做同样的事情,即与32位整数加上“环绕”的总和(有时不进行“溢出检查”)被称为unchecked上下文)。

这是加法模2 32 。我将考虑“未签名”的情况。如果您的32位int使用二进制补码,则它是相同的。 (对于一个数学家来说,二进制补码仍然只是模2 32 的加法(和乘法),我们只为模2 32 的每个等价类选择不同的规范代表。)< / p>

如果我们拥有 all 个非零的32位整数,我们将拥有:

1 + 2 + 3 + … + 4294967295 ≡ 2147483648

实现此目的的一种方法是将第一项和最后一项结合在一起,它们给出零(模2 32 )。然后,第二项(2)和倒数第二项(4294967294)也为零。因此,除中间一个(2147483648)等于和之外的所有项都抵消了。

想象一下,从这种相等性中减去x符号两侧的一个数字(称为)。由此可见,您从2147483648开始并从所有给定的数字中减去(仍然为unchecked)来找到缺失的数字。然后,您会得到缺少的数字:

missingNumber ≡ 2147483648 - x1 - x2 - x3 - … - x4294967294

当然,这与Moonshadow的解决方案相同,只是在以2为模2 32 的整数环中进行。


优美的XOR解决方案(sykora的答案)也可以用相同的方式编写,并且XOR同时用作+- 。也就是说,如果我们有 all 个非零的32位整数,那么

1 XOR 2 XOR 3 XOR … XOR 4294967295 ≡ 0

,然后XOR在符号x的两边都缺少数字来查看:

missingNumber ≡ x1 XOR x2 XOR x3 XOR … XOR x4294967294