Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 合并至少共享2个元素的集合的算法_Algorithm_Set_Graph Theory - Fatal编程技术网

Algorithm 合并至少共享2个元素的集合的算法

Algorithm 合并至少共享2个元素的集合的算法,algorithm,set,graph-theory,Algorithm,Set,Graph Theory,给定一个集合列表: S_1:[1,2,3,4] S_2:[3,4,5,6,7] S_3:[8,9,10,11] S_4:[1,8,12,13] S_5:[6,7,14,15,16,17] 合并共享至少2个元素的所有集合的最有效方法是什么?我想这类似于连接组件的问题。因此,结果将是: [1,2,3,4,5,6,7,14,15,16,17](S_1联盟S_2联盟S_5) [8,9,10,11] [1,8,12,13](S_4与S_1共享1,与S_3共享8,但未合并,因为它们在每个元素中仅共享一

给定一个集合列表:

  • S_1:[1,2,3,4]
  • S_2:[3,4,5,6,7]
  • S_3:[8,9,10,11]
  • S_4:[1,8,12,13]
  • S_5:[6,7,14,15,16,17]
合并共享至少2个元素的所有集合的最有效方法是什么?我想这类似于连接组件的问题。因此,结果将是:

  • [1,2,3,4,5,6,7,14,15,16,17](S_1联盟S_2联盟S_5)
  • [8,9,10,11]
  • [1,8,12,13](S_4与S_1共享1,与S_3共享8,但未合并,因为它们在每个元素中仅共享一个元素)

简单的实现是O(N^2),其中N是集合的数量,这对我们来说是不可行的。这需要对数百万个集合有效。

如果您可以对集合中的元素进行排序,您可以研究在集合中使用。唯一需要的修改是在合并阶段检查重复项。如果找到一个,只需丢弃副本即可。由于mergesort是O(n*log(n)),与朴素的O(n^2)算法相比,这将提供更高的速度


然而,为了真正有效,您应该维护一个排序集并保持其排序,这样您就可以跳过排序阶段,直接进入合并阶段。

一方注意:这取决于发生的频率。如果大多数集合对确实共享至少两个元素,那么在进行比较的同时构建新集合可能是最有效的,如果它们不符合条件,则将其丢弃。如果大多数对不共享至少两个元素,那么将新集合的构建推迟到条件确认之后可能会更有效。

如果您的元素本质上是数字的,或者可以自然排序(即,您可以指定一个值,如1、2、42等),我建议对合并的集合使用基数排序,再做一次练习,学习独特的元素

该算法应该是O(n),并且可以使用位移位运算符和位掩码对基数排序进行大量优化。我曾经为我正在从事的一个项目做过类似的事情,它就像一个符咒。

让我们列出许多名为
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.
通过S的所有元素确定范围(低..高)。 创建一个指向集合的指针数组,其维度为(低、高),名为(M)。 做 将M的所有元素初始化为NULL。 迭代S,一次处理一组,名为(Si)。
置换Si中的所有有序对。(P1,P2)其中P1我不知道如何在小于O(n^2)的时间内完成

每个集合都需要与其他集合进行比较,以查看它们是否包含2个或更多共享元素。这是n*(n-1)/2比较,因此是O(n^2),即使对共享元素的检查需要恒定的时间

在排序中,朴素的实现是O(n^2),但您可以利用有序比较的传递性(例如,您知道quicksort的下分区中没有任何内容需要与上分区中的任何内容进行比较,因为它已经与pivot进行了比较)。这就是导致排序为O(n*logn)的原因

这在这里不适用。因此,除非集合有什么特殊之处,允许我们跳过基于先前比较结果的比较,否则它通常是O(n^2)


Paul。

集合中的值的范围是什么?有整数吗?它们能在一个集合中重复吗?集合中的值是整数,它们不会在每个集合中重复只是为了澄清:在你的例子中,第一次合并是否也应该包括S_3,因为它与S_5共享四个元素?如果我们有a:[1,2,3],B:[1,2,4]和C:[3,4,5]。我们是否先将A和B合并到[1,2,3,4],然后再与C合并(因为A+B与C有2个共同点,而A或B与C都没有2个共同点?我看不出这如何解决查找哪些集合有2个或更多共同元素的问题。这只是显示了如何查找两个集合的并集,我认为这是这个问题中比较容易的部分。我不认为知道一个集合是否有2个或更多共同元素有助于解决问题。)不是所有的。因为你不知道有多少重复项,你无法停止检查它们。这假设一个集合中的所有元素都在低和高之间,这不是真的——或者我弄错了吗?在合并Si之后,你仍然必须排列Si中的所有对,并将它们添加到M(指向M(P1,P2)),然后再移动到集合s(i+1),对吗?否则,这看起来不错。集合{1,2,3},{2,3,4}和{1,4}应该发生什么第一个和第二个被合并,合并后的集合与第三个有两个重复-第三个应该被合并,还是只有集合的原始内容才重要?我想这个答案与前者有关,而不是后者。保罗:是的,这是我之前的评论试图解决的问题。当{2,3,4}与{1,2,3},新合并集合中的置换对需要添加到M.@Claudiu。不,集合不需要是连续的。如果集合中的元素可以排序,重复项将始终彼此相邻。这允许我们将搜索限制在相邻项,即O(1)操作,而不是每次都搜索它们,而是O(n)操作。“集合中的元素可以排序…”即使重复检测为O(1),仍然有O(n^2)要做的比较。无论如何,我们不是在一个集合中寻找重复的项。我们是在两个集合之间寻找重复的项。它们可以是第一个、最后一个或任何其他。对集合中的元素排序,并不意味着重复项将是相邻的。如果在另一个集合中有相同的对,则一对是重复的她的集合。我倾向于认为你是对的,保罗。我在上面做的多路径的事情可能有O(N*N)的行为。它实际上是集合周围重复分布的函数。它