【发布时间】:2011-02-11 22:02:54
【问题描述】:
我正在为一个问题考虑不同的解决方案。假设我们有 K 个已排序的链表,并且我们将它们合并为一个。所有这些列表共有 N 个元素。
众所周知的解决方案是使用优先级队列并从每个列表中弹出/推送第一个元素,我可以理解为什么需要O(N log K) 时间。
但让我们看看另一种方法。假设我们有一些 MERGE_LISTS(LIST1, LIST2) 过程,它合并两个排序列表,这将花费 O(T1 + T2) 时间,其中 T1 和 T2 代表 LIST1 和 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)。
我的朋友告诉我(两天前)这需要O(K N) 时间。所以,问题是——我是不是在某个地方搞错了,还是他真的错了?如果我是对的,为什么不能使用这种“分而治之”的方法来代替优先队列方法?
【问题讨论】:
-
嗯,我想它比 priority_queue 算法更糟糕,因为它使用了很多额外的内存。尽管如此,它更容易实现......嗯:)
-
N在这个问题中定义了所有列表中的元素总数,而不是其中一个列表的平均元素数。 -
我可以理解会有logK行数,但是你能解释一下为什么每一行都是O(n)吗?比如第一行,不会有k*O(n)吧?
-
无论你使用什么策略,都会有 NK 个元素被触及。因此,复杂度不能从 O(NK) 降低。