我有两个大的整数集的和。每组有大约一百万个条目,每个条目是一个正整数,最长为10位数字。
计算和的最佳算法是什么?换句话说,如何有效地计算不在B中的条目列表,反之亦然?代表这两组数据,使这些操作高效的最佳数据结构是什么?
我能想到的最好方法是将这两个集合存储为排序列表,并以线性方式将每个元素与每个元素进行比较。我们可以做得更好吗?
我有两个大的整数集的和。每组有大约一百万个条目,每个条目是一个正整数,最长为10位数字。
计算和的最佳算法是什么?换句话说,如何有效地计算不在B中的条目列表,反之亦然?代表这两组数据,使这些操作高效的最佳数据结构是什么?
我能想到的最好方法是将这两个集合存储为排序列表,并以线性方式将每个元素与每个元素进行比较。我们可以做得更好吗?
Answers:
如果您愿意将集合存储在专门的数据结构中,则可能会遇到一些有趣的复杂性。
让
然后,你可以做的一组操作和一个Δ 乙中,每个Ø (我⋅ 登录|一个| + |乙|预计时间。因此,从本质上讲,您将获得两组的最小大小或对称差异的大小(以较小者为准)。如果对称差异较小,则此方法比线性方法好。即。如果他们有一个大的交叉点。实际上,对于您想要的两个集差运算,这实际上是输出敏感的,因为它们共同构成了对称差的大小。
有关更多信息,请参见Olle Liljenzin(2013)的“ 合流持久性集和地图”。
如果将集合表示为排序的链表,则线性扫描是我所知的最佳方法。运行时间为。
请注意,您不需要成对比较每个元素和B的每个元素。这将导致运行时间为O (| A | × | B |),这更糟。取而代之的是,要计算这两个集合的对称差异,可以使用类似于mergesort中的“ merge”操作的技术,并对其进行了适当的修改以忽略这两个集合共有的值。
更详细地讲,您可以构建如下所示的递归算法来计算,假设A和B表示为链表,其值按排序顺序排列:
difference(A, B):
if len(B)=0:
return A # return the leftover list
if len(A)=0:
return B # return the leftover list
if A[0] < B[0]:
return [A[0]] + difference(A[1:], B)
elsif A[0] = B[0]:
return difference(A[1:], B[1:]) # omit the common element
else:
return [B[0]] + difference(A, B[1:])
我已经用伪Python表示了这一点。如果你不读的Python,A[0]
是链表的头A
,A[1:]
是列表的其余部分,并+
表示名单的串联。出于效率方面的考虑,如果您使用的是Python,则可能不希望完全按上述方式实现它-例如,最好使用生成器,以避免建立许多临时列表-但我想以最简单的形式向您展示想法。此伪代码的目的只是为了说明算法,而不是提出具体的实现。
我认为,如果将集合表示为排序列表,并且希望将输出作为排序列表来提供,则不可能做得更好。从根本上讲,您必须查看和B的每个元素。非正式的理由说明:如果您没有看过任何元素,就无法输出它,因此唯一可以忽略的元素就是您知道它在A和B中都存在,但是如果您不看它的价值,怎么知道它的存在呢?
如果A和B的大小相等,不相交且交织(例如A中的奇数,B中的偶数),则线性时间中的项的成对比较可能是最佳的。
如果A和B包含正好在A或B之一或两者之中的项目块,则可以计算子线性时间中的集合差,并集和交集。例如,如果A和B的一项完全不同,则可以在O(log n)中计算出差异。
long
可以存储32个元素或1个byte
,8个元素。因此1M条目只能存储在约125K RAM中!根据问题的实现方式,该存储可以比其他表示有效得多...