从两个非常大的数组中查找公共元素

时间:2012-01-23 14:51:15

标签: c++ algorithm

有两个整数数组,每个都在非常大的文件中(每个都大于RAM)。如何在线性时间内找到数组中的公共元素。

我找不到解决这个问题的好方法。有任何想法吗?

6 个答案:

答案 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)时间内完成:

  1. 获取文件的一部分,使用基数排序对其进行排序,写入临时文件。重复,直到所有数据完成。这部分是O(n)
  2. 合并已分类的部分。这也是O(n)。你甚至可以跳过重复的数字。
  3. 在已排序的文件中找到一个公共的整数子集:比较数字,如果它们相等则将其写下来,然后在文件中用较小的数字提前一步。这是O(n)。

    所有操作都是O(n),最终算法也是O(n)。

    编辑:如果你有足够的内存用于位图,位图方法要快得多。此方法适用于任何固定大小的整数,例如64位。尺寸为2 ^ 31 Mb的位图至少在几年内不实用:)