处理大量输入时应该选择什么

时间:2013-04-05 23:03:36

标签: algorithm sorting data-structures hashtable

我最近偶然发现了一个问题

当每个序列可以有重复的数字并且大小相当大(接近一百万)并且处理的数据类型为Long时,如何找到两个序列的交集。

我考虑过排序和找到交叉点,这不是一个可行的解决方案 我甚至认为哈希表不起作用,因为空间考虑必须是最佳的

有人可以建议处理它的更好方法吗?

感谢阅读帖子

4 个答案:

答案 0 :(得分:2)

该问题声称“排序和找到交叉点......不是一个可行的解决方案”。然而,从编码的简易性和清晰度的观点来看,分类是最佳解决方案之一。对于任何一次性问题,花费10分钟编写排序解决方案比花费15分钟编写散列解决方案或半小时编写特殊树程序更合理。

使用下面显示的python代码排序一百万双,在我的旧PC(AMD Athlon 5000,大约2GHz)上花费大约1.3秒,并且可能比当前处理器快四到五倍。按时间排序两个数组O(n lg n),然后根据问题的要求在时间O(n)中查找匹配,可能需要在现代PC上花费一两秒。

In [237]: import random

In [238]: v = [random.random() for i in range(1000000)]

In [239]: %time u = sorted(v)
CPU times: user 1.32 s, sys: 0.00 s, total: 1.32 s
Wall time: 1.33 s

注意,question #8630965是指在1.168秒内对一百万个浮点值进行排序。

答案 1 :(得分:1)

假设long是固定大小,比如64位。规划深度最大为64的部分二叉树。对于第一个序列中的每个数字,您将要生长树。所有叶子都出现在深度64处。每个叶子有两个整数,它们是引用两个序列的计数器。

for each number n in the first list
    current_node = root
    for i ranging from 1 to 64
        if the i-th bit of n is zero
            grow/traverse edge labeled 'zero' from current_node
        else
            grow/traverse edge labeled 'one' from current_node
        set current_node to be at end of this edge
    if the current_node (now at depth 64) is brand new
        set the node's first counter to 1; second counter to zero
    else
        increment current_node's first counter by 1

第二部分是处理第二个列表,而是更新第二个计数器。如果需要,您也可以跳过创建新节点,因为那里不会有任何交叉点。然后遍历整个树,看看两个计数器都在非零位置。

答案 2 :(得分:1)

我认为每个列表包含2M条目的哈希表(因此哈希表负载保持相当低,为50%或更低)是一个不错的选择。如果您使用最简单的实现,那么快速,而不是非常大,只有2M * 4B(您的长度是4字节长,对吧?)。

如果列表中的唯一值很少,则排序/搜索树将比哈希表更紧凑,但如果存在大量唯一数字,则它将比哈希表更大(您需要子/父指针)在树节点中,这是开销)。

统计数据是什么?

答案 3 :(得分:0)

对我来说,问题归结为:

  • 使用某种数据结构表示稀疏第一个输入
  • 将第二个输入作为关键字遍历到前一步骤中计算的数据结构中。

我最初的想法也是哈希表。但是我们每个数字都需要一个节点。 另一位作者已经有了这个想法。

我的第二个念头是B +树。我们可以使用这棵树映射稀疏集。叶子可以包含一系列的nos ...这样,我们可以在寻找与第二个输入集的交集时燃烧更多的cpu来搜索叶子。您确实支付内部节点中b +树索引的成本。假设我们不在树中存储重复...不需要交集。我们可以使用基于位的存储来优化叶子以减少空间。