我最近偶然发现了一个问题
当每个序列可以有重复的数字并且大小相当大(接近一百万)并且处理的数据类型为Long时,如何找到两个序列的交集。
我考虑过排序和找到交叉点,这不是一个可行的解决方案 我甚至认为哈希表不起作用,因为空间考虑必须是最佳的
有人可以建议处理它的更好方法吗?
感谢阅读帖子
答案 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 +树索引的成本。假设我们不在树中存储重复...不需要交集。我们可以使用基于位的存储来优化叶子以减少空间。