您将获得2 ^ 32-2个唯一数字,范围从1到2 ^ 32-1。将所有数字都放入内存是不可能的(因此排序不是一种选择)。系统会要求您找到丢失的号码。解决这个问题的最佳方法是什么?
假设您不能使用大整数并且仅限于32位整数。
int
通过标准传入。
答案 0 :(得分:32)
主要编辑:相信我会让事情变得更加艰难。
我在这里假设数字是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