【问题标题】:What would be the time complexity of merging k sorted linked lists by using the concept of merging 2 sorted lists?使用合并 2 个已排序列表的概念合并 k 个已排序链表的时间复杂度是多少?
【发布时间】:2021-05-03 12:27:28
【问题描述】:

如果我使用合并2个排序链表的算法,我想知道merging k sorted lists的真实时间复杂度。

我在某处看到时间复杂度为 O(nk),某处为 O(nk^2)。 (k 是排序列表的数量,n 是列表中元素的数量)。 所以我对这个问题的时间复杂度感到困惑。

请告诉我这个问题的真实时间复杂度。

【问题讨论】:

  • 它应该是 O(N*K)(其中 N*K = 所有列表中的总元素)并使用 heap O(N * logK)
  • youtu.be/wugaUVZ8PVw?t=147 请在 2:29 到 9:00 之间观看此视频...(在这种情况下,时间复杂度为 O(nk^2))。
  • “我在某处看到时间复杂度为 O(nk),某处为 O(nk^2)”:您能否添加这两个声明的来源 里面问题?

标签: data-structures linked-list time-complexity


【解决方案1】:

如果我使用合并 2 个已排序链表的算法,我想知道合并 ? 已排序列表的真实时间复杂度。

有多种算法可供选择。

我们将?定义为一个排序列表中值的(最大)个数,因此值的总数以??为界。 ? 的明确定义很重要,因为有些人会将其定义为所有列表中值的 total 数量 - 这显然会导致不同的公式。我将值的总数定义为?。所以?=??

朴素算法

此算法合并前两个列表,然后将结果与第三个列表合并,然后将结果与第四个列表合并,......等等。

该算法需要执行 ?−1 次合并,每次合并将比前一次合并 ? 更多的项目。第一次合并涉及两个?元素列表,所以它是 O(2?)

因此我们有以下关系?:

      ?(2) = O(2?)
?(?) = ?(?−1) + O(??)

所以:

      ?(?) = O(?∑?=2..??) = O(??²) = O(??)

最后一步使用triangular numbers的公式

分而治之算法

(二进制)分治算法定义了当您只有 2 个列表时的基本情况,并将它们与已知算法合并。在所有其他情况下,它会合并来自递归的两个列表。这确实是merge sort 使用的原理。

现在递归关系如下:

      ?(2) = O(2?)
?(?) = 2?(?/2) + O(??)

如果我们将这个关系展开一次,我们得到:

     ?(?) = 2(2?(?/4) + O(??/2)) + O(??) = 4?(?/4) + O(??) + O(??)

如果再次展开:

      ?(?) = 8T(?/8) + O(3??)

log2? - 1 次扩展后:

      ?(?) = (?/2)?(2) + O(??log?)

代入?(2),我们得到:

      ?(?) = O(??) + O(??log?) = O(??log?) = O(?log?)

基于堆的算法

当您创建一个二进制最小堆时,其中每个条目都是一个链表,由其第一个节点的值作为键,然后您可以重复从堆中提取具有最小元素的列表,从该列表中提取该元素,然后将该列表再次插入堆中,它将根据其新键找到它的位置(因为它现在少了一个节点)。如果列表变为空,则不再将其插入堆中。

构建堆的成本为 O(?)。一个堆提取和插入的成本为 O(log?)。有 ?? 提取要做,所以复杂度是 O(?) + O(??log?) = O(??log?) = O(?log?)

【讨论】:

  • youtu.be/kpCesr9VXDA?t=141 请观看此视频(从 2:20 到 4:05),他声称对于简单算法来说时间复杂度为 O(nk)。我认为他(告诉 O(nk) 的人)错了。
  • @AbhishekJaiswal,在该视频中将 ? 定义为 total 值的数量,因此它也是正确的。
猜你喜欢
  • 1970-01-01
  • 2014-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-11
  • 1970-01-01
相关资源
最近更新 更多