【问题标题】:BUILD-MAX-HEAP running time for array sorted in decreasing orderBUILD-MAX-HEAP 运行时间降序排列的数组
【发布时间】:2016-09-25 21:16:12
【问题描述】:

我知道 BUILD-MAX-HEAP 在堆排序中的运行时间是O(n)。但是,如果我们有一个已经按降序排序的数组,为什么我们还有 O(n) 用于 BUILD-MAX-HEAP 的运行时间?
不应该是O(1) 之类的东西吗?它已经从最大值到最小值排序了,所以我们不需要 MAX-HEAPIFY。

我的理解正确吗?谁能给我解释一下?

【问题讨论】:

    标签: algorithm sorting heapsort max-heap


    【解决方案1】:

    你是对的。当然可以是O(1)。当您确定您的列表已排序后,您可以将其用作最大堆。

    使用数组的堆的常见实现将这种行为用于其元素位置:

    childs[i] = 2i+1 and 2i+2
    parent[i] = floor((i-1)/2)
    

    此规则适用于已排序的数组。 (max-heap 递减,min-heap 递增)。

    注意,如果您需要首先检查列表是否已排序,那么它当然仍然是O(n)

    编辑:堆排序复杂性
    即使数组可能已排序并且构建堆实际上可能需要O(1)。每当您执行堆排序时,您仍然会得到O(n log n)
    正如 cmets 中所说,堆排序正在执行 nextract-max 的调用。每个提取操作都需要O(log n) - 我们最终的总时间复杂度为O(n log n)
    如果数组未排序,我们将得到O(n + nlogn) 的总时间复杂度,它仍然是O(n log n)

    【讨论】:

    • 感谢您的回答。但是,为什么堆排序仍然有O(n lg n)的运行时间,即使BUILD-MAX-HEAP只需要时间O(1)。为什么不是O(1 lg n) = O(lg n)
    • @mskeira 因为执行堆排序的时间主要由对 extract-max 的 n 个调用支配,每个调用都需要 log n 时间,即使堆最初是完全排序的。堆排序有一些变体实现,它们在“接近排序”的输入上表现更好。
    • @mskeira 我已经相应地编辑了我的答案,尽管它有点超出了问题的范围。如果您认为此答案正确,请考虑通过单击我的答案旁边的 V 来接受它。很高兴为您提供帮助。
    • @rici 感谢您的评论。我已经更新了我的答案以包括这一点。
    【解决方案2】:

    如果您知道该数组已按降序排序,则无需对其进行排序。如果您希望它按升序排列,您可以在 O(n) 时间内反转数组。

    如果你不知道数组是否已经排序,那么它需要 O(n) 来确定它是否已经反向排序。

    从反向排序数组构建最大堆被认为是 O(n) 的原因是您必须从第 n/2 项开始,并且向后工作,确保该元素不小于其子元素。即使只有 n/2 个检查,它也被认为是 O(n),因为执行的操作数与要检查的项目总数成正比。

    顺便提一下,有趣的是,您可以从一个反向排序的数组构建一个最大堆,这比检查该数组是否是反向排序的要快。

    【讨论】:

      猜你喜欢
      • 2013-07-17
      • 2019-05-23
      • 1970-01-01
      • 2018-01-10
      • 1970-01-01
      • 2021-11-19
      • 2010-09-19
      • 1970-01-01
      • 2017-07-16
      相关资源
      最近更新 更多