合并k个已排序的链表 - 分析

时间:2010-04-24 17:07:33

标签: algorithm merge list

我正在考虑针对一个问题的不同解决方案。假设我们有K个已排序的链表,我们将它们合并为一个。所有这些列表一起有N个元素。

众所周知的解决方案是使用每个列表中的优先级队列和弹出/推送第一个元素,我可以理解为什么需要O(N log K)时间。

但是让我们来看看另一种方法。假设我们有一些MERGE_LISTS(LIST1, LIST2)过程,它合并了两个排序列表,它需要O(T1 + T2)时间,其中T1T2代表LIST1和{{1 }} sizes。

我们现在所做的通常意味着将这些列表配对并将它们逐对合并(如果数字是奇数,则最后一个列表,例如,可以在第一步中忽略)。这通常意味着我们必须制作合并操作的以下“树”:

LIST2代表N1, N2, N3...尺寸

  • LIST1, LIST2, LIST3
  • O(N1 + N2) + O(N3 + N4) + O(N5 + N6) + ...
  • O(N1 + N2 + N3 + N4) + O(N5 + N6 + N7 + N8) + ...

很明显,这些行中会O(N1 + N2 + N3 + N4 + .... + NK),每个行都会执行log(K)次操作,因此O(N)操作的时间实际上等于MERGE(LIST1, LIST2, ... , LISTK)

我的朋友告诉我(两天前)需要O(N log K)时间。所以,问题是 - 我是否曾在某处或者他真的错了?如果我是对的,为什么不能使用这种“分而治之”的方法而不是优先队列方法呢?

4 个答案:

答案 0 :(得分:3)

根据您的描述,听起来您的过程确实是O(N log K)。它也可以使用,所以你可以使用它。

我个人会使用带优先级队列的第一个版本,因为我怀疑它会更快。它在粗糙的大O意义上并不快,但我认为如果你实际计算出两者的比较和存储数量,第二个版本将需要多倍的工作。

答案 1 :(得分:3)

如果要合并少量列表,这种成对方案可能比优先级队列方法更快,因为每个合并的操作极少:基本上只有一个比较和每个项目的两个指针重新分配(转换为一个新的单链表)。如您所示,O(N log K)log K步骤处理每个N个项目。

但我认为,最佳优先级队列算法是O(sqrt(log K))O(log log U)用于插入和删除(其中U是可能的不同优先级的数量) - 如果您可以优先排序使用值而不必使用比较 - 所以如果你要合并可以给出的项目,例如整数优先级,K很大,那么你最好使用优先级队列。

答案 2 :(得分:1)

这是O(2*log(K)*N)这是O(N*log(K)),因为您只2N次添加O(log(K))中的优先级队列,所以您的复杂性最差。

或者您可以将所有元素推送到O(2N)中的向量中。并在O(2n*log(2n))中对其进行排序。然后你有O(2N+2N*Log(2N)),这是O(N*LOG(N)),非常K = N;

答案 3 :(得分:0)

它确实在O(N*log K)中运行,但不要忘记,O(N*log K)O(N*K)的子集。即你的朋友也没错。