有两个整数数组,每个都在非常大的文件中(每个都大于RAM)。如何在线性时间内找到数组中的公共元素。
我找不到解决这个问题的好方法。有任何想法吗?
答案 0 :(得分:12)
一个文件的一次传递构建一个位图(如果整数范围对于内存中的位图来说太大,则构建一个Bloom filter。)
另一个文件中的一个传递找到重复项(或者如果使用Bloom过滤器则为候选项)。
如果您使用Bloom过滤器,则结果是概率性的。新的通行证可以减少误报(布隆过滤器没有假阴性)。
答案 1 :(得分:6)
假设整数大小为4个字节。 现在我们可以有最多2 ^ 32个整数,即我可以有一个2 ^ 32位(512 MB)的位向量来表示每个位重复1个整数的所有整数。 1.使用全零初始化此向量 2.现在浏览一个文件,如果找到整数,则将此向量中的位设置为1。 3.现在浏览其他文件并查找位Vector中的任何设置位。
时间复杂度O(n + m) 空间复杂度512 MB
答案 2 :(得分:4)
显然,您可以使用哈希表来查找具有O(n)时间复杂度的公共元素。
首先,您需要使用第一个数组创建一个哈希表,然后使用此哈希表比较第二个数组。
答案 3 :(得分:1)
假设有足够的RAM来保存给定文件阵列(FA)的5%哈希值。
所以,我可以将文件数组(FA1和FA2)分成20个块 - 比如做一个MOD 20的内容。我们得到FA1(0)...... FA1(19)和FA2(0)...... FA2(19)。这可以在线性时间内完成。
在内存中散列FA1(0)并将FA2(0)的内容与此散列进行比较。哈希和检查存在是恒定时间操作。
销毁此哈希并重复FA1(1)... FA1(19)。这也是线性的。因此,整个操作是线性的。
答案 4 :(得分:-1)
假设您正在讨论具有相同大小的整数,并以二进制模式写入文件,您首先对2个文件进行排序(使用快速排序,但读取和写入文件“偏移”)。 然后你只需要从2个文件的开头移动,并检查匹配,如果你有匹配将输出写入另一个文件(假设你也不能将结果存储在内存中)并继续移动文件直到EOF。
答案 5 :(得分:-1)
排序文件。对于固定长度的整数,可以在O(n)时间内完成:
在已排序的文件中找到一个公共的整数子集:比较数字,如果它们相等则将其写下来,然后在文件中用较小的数字提前一步。这是O(n)。
所有操作都是O(n),最终算法也是O(n)。
编辑:如果你有足够的内存用于位图,位图方法要快得多。此方法适用于任何固定大小的整数,例如64位。尺寸为2 ^ 31 Mb的位图至少在几年内不实用:)