【问题标题】:build heap time complexity worst case vs upper bound / tight upper bound构建堆时间复杂度最坏情况与上限/严格上限
【发布时间】:2015-03-09 09:54:05
【问题描述】:

HERE 据说构建堆的最坏情况时间复杂度是 O(nlogn) 但上限是 O(n)。

上限与最坏情况的时间复杂度有何不同,以及何时比其他更有意义。 严格的上限有什么不同吗?

【问题讨论】:

  • 我相信某处存在一些误解。他们可能想说 heapify() 是 O(n),尽管乍一看它似乎是 O(n log n) 算法。此外,如果通过按顺序执行堆插入来天真地实现,则复杂度确实为 O(n log n)。我的猜测——他们随意使用“最坏情况”,而不是严格意义上的数学。
  • 感谢您的回复。我不认为这是打字错误。你能检查一下吗geeksforgeeks.org/nearly-sorted-algorithm 即使在第二个解决方案中,他们提议使用堆,他们说要形成 k 个元素的堆,这将需要 O(k)
  • 维基百科和我的 CS 教科书一样 - 构建堆的复杂性是 O(n)。输入数据分布无关紧要——它总是 O(n)。
  • heapify 和 build heap 不是一回事。我这里说的是构建堆
  • 从一组输入构建一个堆是并且将始终是 O(n) (无论所述输入和堆的分支因子如何 - 例如。二进制三元,...)。您只是误读了您提供的链接:它说“虽然最坏的情况复杂度看起来像 O(nLogn),但时间复杂度的上限是O(n)。”

标签: java algorithm heap time-complexity


【解决方案1】:

构建一个堆(也称为Heapify总是 O(n),无论输入分布或堆的分支因子(二元、三元堆...)。

您误读了提供的链接,它指出:(重点是我的)

虽然最坏情况的复杂度看起来像 O(nLogn),但时间复杂度的上限是 O(n)。

基本上,heapify 是如何工作的? (为了清楚起见,我假设我们使用的是二进制堆)

首先让我们回忆一下二叉堆的堆条件是什么(使用数组A):

对于任意 i ∈ [0, [N/2], A[i] ≤ A[2i+1] AND A[i] ≤ A[2i+2]

注意:对于从索引 1 开始的数组,您通常会发现相同的条件。在这种情况下,您只需“删除”1,即。 2i+1 变成 2i,2i+2 变成 2i+1。

为什么这种情况仅限于堆的前半部分?很简单,对于任何 i > N/2,2i+1 和 2i+2 都不是有效索引。

HEAPIFY
输入: N 个元素的数组
输出: 相同的 N 个元素的数组,强制执行堆条件

void sink(int [] A, int i, int n) {
    int highest = 2*i+1;
    if (2*i+1 >= n)
        return;
    if (2*i+2 < n && A[2*i+2] > A[highest])
        ++highest;
    if (A[i] < A[highest]) {
        swap(A, i, highest);
        sink(A, highest, n);
    }
}

void heapify(int [] A, int n) {
    for (int i = n/2; i >= 0; --i) {
        sink(A, i, n);
    }
}

假设我们有一个完整的二进制堆,这样的堆正好包含 N = 2h+1 - 1 个元素,对于给定的整数 h >= 0。查看堆成一棵树。索引 0 是树的根(高度 1),索引 1,2 是该根的子节点(高度 0),依此类推。树的高度是整数h。

算法从高度 h-1 开始。高度为 h-1 的 2h-1 元素在下沉时最多可以移动一次。然后,高度为 h-2 的 2h-2 元素每个元素最多可以触发 2 次交换...根(高度为 0 的 20 元素)可以触发最多 h 交换。最后,构建堆的最大交换次数是:

MaxSwap = sum(k=0..h-1, 2k.(h-k)) = 2h+1 - h - 2 ≤ 2h+1 - 1 = N

构建堆的最大比较次数是最大交换次数的两倍。 对于任何“不完整”的堆,即。 2h ≤ N h+1 - 1,推理仍然成立。

结论:Heapify O(N) 其中N是堆的大小。


奖金

从输入数组构建 Maxheap 的运行 Java 示例:here

【讨论】:

  • @Walt,在这里,heapify() 构建了一个堆。一直以来都是如此。
  • 我看错了什么?没有得到你。我认为您所说的与我所说/询问的内容相同,即 buildHeap(in your world-heapify) 是 O(n)。
  • @Walt 你误读了链接,因为它从不说 BuildHeap 的最坏情况复杂度是 O(NlogN),它说它看起来像是的。
猜你喜欢
  • 2021-09-27
  • 1970-01-01
  • 2011-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-21
  • 1970-01-01
相关资源
最近更新 更多