给出一组集合:
合并至少共享2个元素的所有集合的最有效方法是什么?我想这类似于连接组件问题。结果将是:
天真的实现是O(N ^ 2),其中N是集合的数量,这对我们来说是行不通的。这需要对数百万套有效。
答案 0 :(得分:3)
Let there be a list of many Sets named (S)
Perform a pass through all elements of S, to determine the range (LOW .. HIGH).
Create an array of pointer to Set, of dimensions (LOW, HIGH), named (M).
do
Init all elements of M to NULL.
Iterate though S, processing them one Set at a time, named (Si).
Permutate all ordered pairs in Si. (P1, P2) where P1 <= P2.
For each pair examine M(P1, P2)
if M(P1, P2) is NULL
Continue with the next pair.
otherwise
Merge Si, into the Set pointed to by, M(P1, P2).
Remove Si from S, as it has been merged.
Move on to processing Set S(i + 1)
If Si was not merged,
Permutate again through Si
For each pair, make M(P1, P2) point to Si.
while At least one set was merged during the pass.
我的头说这是关于秩序(2N ln N)。 带上一粒盐。
答案 1 :(得分:2)
如果您可以订阅集合中的元素,则可以在集合上使用Mergesort。唯一需要的修改是在合并阶段检查重复项。如果找到一个,只需丢弃副本。由于mergesort是O(n * log(n)),与初始O(n ^ 2)算法相比,这将提供非常快的速度。
但是,要真正有效,您应该维护一个有序集并对其进行排序,以便您可以跳过排序阶段并直接进入合并阶段。
答案 2 :(得分:1)
一方面注意:这取决于这种情况发生的频率。如果大多数集合做共享至少两个元素,那么在您逐步完成比较的同时构建新集合可能是最有效的,如果它们没有,则抛弃它符合条件。如果大多数对不共享至少两个元素,那么推迟构建新集合,直到确认条件可能更有效。
答案 3 :(得分:1)
我不知道如何在低于O(n ^ 2)的情况下完成这项工作。
需要将每个集合与其他集合进行比较,以查看它们是否包含2个或更多共享元素。这是n *(n-1)/ 2比较,因此O(n ^ 2),即使检查共享元素需要恒定时间。
在排序中,天真的实现是O(n ^ 2),但是你可以利用有序比较的传递性质(例如,你知道,快速排序的下层分区中的任何内容都不需要与之中的任何内容进行比较上部分区,因为它已经与枢轴进行了比较)。这就是导致排序为O(n * log n)的原因。
这不适用于此处。因此,除非这些集合中有一些特殊内容允许我们根据先前比较的结果跳过比较,否则它通常会为O(n ^ 2)。
保罗。
答案 4 :(得分:0)
如果你的元素本质上是数字的,或者可以自然地排序(即你可以指定一个值,如1,2,42等......),我建议在合并的集合上使用基数排序,并且进行第二次传递以获取独特的元素。
此算法应为O(n),您可以使用按位移位运算符和位掩码来优化基数排序。我为我正在研究的项目做了类似的工作,它就像一个魅力。