2008-11-23 40 views
12

鉴于集列表集:算法合并共享至少2个元素

  • 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]

什么最e合并所有共享至少两个元素的集合的方法很简单吗?我想这与连接组件问题很相似。因此,结果将是:

  • [1,2,3,4,5,6,7,14,15,16,17](S_1 UNION S_2 UNION S_5)
  • [8,9 10,11]
  • [1,8,12,13](S_4股1 S_1,和8 S_3,但不被合并,因为它们只共享在每一个元件)

朴素实施O(N^2),其中N是集合的数量,这对我们来说是行不通的。这需要对数百万套有效。

+0

集合中的值的范围是多少? – 2008-11-23 20:35:01

+0

有没有整数?他们可以在一套内重复吗? – EvilTeach 2008-11-23 20:38:08

+0

集合中的值是整数,并且它们不在每个集合中重复 – bajafresh4life 2008-11-23 20:47:32

回答

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)。 带上一粒盐吧。

2

如果您可以订购集合中的元素,则可以在集合上使用Mergesort进行查看。所需的唯一修改是在合并阶段检查重复项。如果找到一个,只需丢弃重复。由于mergesort是O(n * log(n)),与天真的O(n^2)算法相比,这将提供更快的速度。

但是,为了真正有效,您应该维护一个已排序的集合并对其进行排序,以便您可以跳过排序阶段并直接进入合并阶段。

1

一面注意:这取决于发生的频率。如果大多数对集合至少共享两个元素,那么在逐步比较时同时构建新集合可能最有效,如果它们与条件不匹配,则将其丢弃。如果大多数对不是至少共享两个元素,则推迟构建新组,直到确认条件可能更有效。

0

如果你的元素本质上是数值型的,或者可以自然排序(即你可以指定一个值,如1,2,42等),我会建议在合并集上使用基数排序,并进行第二轮挑​​选独特的元素。

该算法应该是O(n),并且您可以使用按位移位运算符和位掩码相当多地优化基数排序。我为我正在进行的一个项目做了类似的事情,它的作用就像一个魅力。

1

我不明白如何在小于O(n^2)的情况下完成此操作。

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

在排序中,天真的实现是O(n^2),但是您可以利用有序比较的传递性质(例如,您不知道快速排序的较低分区中什么都不需要与任何东西进行比较在上面的分区中,因为它已经与支点进行了比较)。这就是排序结果为O(n * log n)的原因。

这不适用于此。所以除非这些集合有什么特别之处,让我们可以根据以前的比较结果来跳过比较,否则一般会是O(n^2)。

Paul。

相关问题