编程珍珠:找到一个整数至少出现两次

时间:2011-04-02 06:56:55

标签: algorithm programming-pearls

在第2.6节和问题2中,原始问题是这样的:

“鉴于包含4,300,000,000个32位整数的顺序文件,如何找到至少出现两次的整数?”

我对此练习的问题是:上述问题的技巧是什么?这个问题属于哪种通用算法类别?

5 个答案:

答案 0 :(得分:10)

创建一个长度为2 ^ 32位(初始化为零)的位数组,大约512MB,可以放入任何现代机器的RAM中。

开始读取文件,int by int,使用与int的值相同的索引检查位,如果设置了位,则发现重复,如果为零,则设置为1并继续下一个int来自档案。

诀窍是找到合适的数据结构和算法。在这种情况下,一切都适合RAM,具有合适的数据结构,可以使用简单有效的算法 如果数字是int64,您需要找到合适的排序策略或多次通过,具体取决于您可用的额外存储空间。

答案 1 :(得分:7)

鸽笼原则 - 如果你在M鸽笼中有N只鸽子,并且N> M,那么在一个洞中至少有2只鸽子。这组32位整数是我们的2 ^ 32个鸽笼,我们文件中的43亿个数字是鸽子。自4.3x10 ^ 9> 2 ^ 32,我们知道有重复。

您可以应用此原则来测试我们正在查找的副本是否在数据的子集中,而代价是读取整个文件,而不是一次只加载到RAM中 - 只需计算您在测试范围内看到数字的次数,并与该范围内的整数总数进行比较。例如,要检查1,000,000到2,000,000之间的重复:

int pigeons = 0;
int pigeonholes = 2000000 - 1000000 + 1; // include both fenceposts
for (each number N in file) {
  if ( N >= 1000000 && N <= 2000000 ) {
    pigeons++
  }
}
if (pigeons > pigeonholes) {
  // one of the duplicates is between 1,000,000 and 2,000,000
  // try again with a narrower range
} 

选择要检查的范围大小与您想要读取16GB数据的次数取决于您:)

就一般算法类别而言,这是一个组合学(数学计算)问题。

答案 2 :(得分:0)

我也在寻找相同的东西,我遇到了这个[链接]:http://mikedebo.ca/2008/04/21/programming-pearls-solutions-to-exercises-2a-c/想到分享同样的东西。

答案 3 :(得分:-1)

如果你的意思是32位正整数, 我认为这个问题不需要一些特殊的算法 或诀窍解决。只需一个简单的观察就可以得到预期的解决方案。

我的观察是这样的,顺序文件只包含 32位整数(从0到2 ^ 31 - 1)。假设你把所有这些都放了 在该文件中,您最终会得到2 ^ 31行。你可以看到 如果再次放置这些正整数,最终会得到2 ^ 31 * 2行 它小于4,300,000,000。

因此,答案是整数正整数,范围从0到2 ^ 31 - 1。

答案 4 :(得分:-1)

对整数进行排序并循环遍历它们以查看连续的整数是否重复。如果你想在内存中这样做,它需要16GB内存,今天的机器可以使用。如果无法做到这一点,您可以使用mergesort和商店中间数组对数字进行排序。

我的第一个实现尝试是使用unix的sortuniq命令。