在第2.6节和问题2中,原始问题是这样的:
“鉴于包含4,300,000,000个32位整数的顺序文件,如何找到至少出现两次的整数?”
我对此练习的问题是:上述问题的技巧是什么?这个问题属于哪种通用算法类别?
答案 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的sort
和uniq
命令。