所以我们有大约 500 万个数组:
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;1000 万] 范围内。
我们必须存储字符串和整数。但是是的,我们可以只使用索引作为整数,稍后再进行替换。1000 万个字符串并不算多,这就是我在示例中使用整数而不是字符串的原因。但实际的原始数据是字符串: ['abcdef', 'abc', 'def', 'fghf'...] (正如我所写的,有 1000 万个唯一字符串)。
有什么方法可以更快地做到这一点?特别是如果数据无法放入内存(我们可以将字符串存储为元素,而不仅仅是整数)?也许是一些棘手的 map\reduce 东西......甚至是 GPU 计算。欢迎任何解决方案 - 想法、算法、链接、代码片段。谢谢你们!
更新。我发现有趣的帖子可能会有所帮助: