查找数百万个阵列的交叉点

时间:2013-09-06 15:25:38

标签: arrays algorithm mapreduce complexity-theory intersection

所以我们有大约5百万个数组:

1) [1, 2, 3, 4, 5, 6]
2) [1, 4, 5]
3) [1, 4, 6, 9, 10]
4) ...

差不多。我们需要找到每个数组之间的交集:

1st array intersection with 2nd: [1, 4, 5]; with 3rd: [1, 4, 6]...
2nd array intersection with 1st: [1, 4, 5]; with 3rd: [1, 4]...
3rd array intersection with 1st: [1, 4, 6]; with 2nd: [1, 4]...

所以看起来明显的算法是2个嵌套循环,它给出了复杂度O(n * n)或其周围的东西。即使我们存储已经计算过的交叉点(由于内存限制可能是不可能的),它也会给我们提供类似~O(n * n / 2)的东西。这是一个非常粗略的复杂度计算,但无论如何它需要5毫升* 5毫升/ 2次迭代。即使我们把所有东西都放在RAM中,这太过分了。

但是有一个技巧。我们并不需要知道所有的交叉点,我们只需要大约20,000个交叉点。因此,我们可以省略那些只包含几个交叉点的数组(我们也可以将它们称为“共享元素”):

1st array intersection with Nth, Mth, Kth... (20,000 of the largest intersections).

大约有1000万个可能的元素,因此数组的每个元素都在[1; 10毫升]的范围内。

我们必须存储字符串以及整数。但是,是的,我们可能只使用索引作为整数,并在以后执行替换。千万字符串不是太多,这就是我在示例中使用整数而不是字符串的原因。但实际的原始数据是字符串:['abcdef','abc','def','fghf'...](正如我写的那样,有1000万个唯一字符串)。

有没有办法更快地完成?特别是如果数据不能适合内存(我们可以将字符串存储为元素,而不仅仅是整数)?也许一些棘手的地图\减少东西......甚至GPU计算。欢迎任何解决方案 - 想法,算法,链接,代码片段。谢谢你们!

更新。我发现了一些有用的帖子可能会有所帮助:

2 个答案:

答案 0 :(得分:1)

很高兴了解有关数据性质的更多信息,然后尝试查看是否可以使用map reduce方法。原因如下:

我在想你应该从所有数组中所有元素的Count Sort O(n)开始。这样你就可以找到频率很高的值。

我的理论是,你的长交叉点会有一些常见元素出现在许多数组中,而其他一些元素则显示较少。

在Count Sort中,您将存储元素X出现的每个数组的地址。

下一步将从显示最多的元素开始,并尝试找出包含该元素的数组的交叉点。我不是在谈论只关注共享最高元素的数组的交叉点,我只是希望将O(NxN)进程减少到合理的N值而不是数百万。

这就是为什么我认为了解字符串元素的本质可能会有所帮助。例如,如果这些数组包含:City,Street,Race,Income等等,那么在走出显示很多的值时,您可以大量使用该信息。

另外,如果您确实拥有City,Street,Income这样的类别,我认为您可以利用标准的Mapr-Reduce方法,使您的Tuple成为Reducer的关键。

答案 1 :(得分:0)

如果我们改变问题并说出每个字符串中有多少是在其他字符串中,而不是交集,Aho-Corasick算法可能会派上用场。它是内存密集型的。它的预处理时间为O(n)。它的运行时间为O(m)(m是模式长度)。如果匹配太多,则性能会降低。 由于您需要找到每个字符串与每个字符串的匹配,因此复杂性将是二次的。