使用堆在O(n + klogk)中以排序顺序输出数组中的最大k个元素?

时间:2018-02-20 22:42:01

标签: heap big-o

我正在尝试将算法的运行时间降低到O(n + klogk),但我似乎无法做到这一点。我通过使用最小堆获得O(n + nlogk)。基本算法如下:

  1. 构建给定数组的前k个元素(arr [0]到arr [k-1])的Min Heap MH。 O(k)的

  2. 对于每个元素,在第k个元素(arr [k]到arr [n-1])之后,将它与MH的根进行比较。 O((N-K)的logK)

  3. 最后,MH有k个最大元素,MH的根是第k个最大元素。调用extractMin k次以获得O(klogk)。

  4. 这得到O(k +(n-k)Logk + kLogk),等于O(k + nlogk)。但我需要O(n + klogk)。

    我不知道如何使用min heap更快地完成它。有什么建议?

1 个答案:

答案 0 :(得分:2)

使用这种min-heap方法的问题是你必须不断处理整个数组的其余部分,在n前面给你一个log k因子。

通过使用类似于分而治之的策略,有一种方法可以减少实际提取第一个k元素所做的工作快速排序这会以指数方式减少必须处理的数组部分。

  1. 选择随机数据元素。
  2. 将数组划分为比枢轴更大和更小的数组,就像在快速排序中一样。假设左侧分区中有L,右侧有R
  3. 如果k == L那么我们就完成了:数组中的第一个k元素是最小的。
  4. 如果k < L然后从1继续,则仅处理左侧分区。
  5. 如果k > L然后从1继续,则使用新值k' = k - L处理正确的分区。
  6. 如果上面的描述含糊不清(编辑:它可能是),这个方法是众所周知的,并且有很多来源(SO here's one,带代码)。

    假设在平均情况下,枢轴近似地将数组分成两个相等的一半(这也是理想情况),时间复杂度递归关系由T(m) = T(m/2) + O(m)给出,这意味着上述算法<强> O(n)

    在此之后,数组的第一个k元素是无序的,因此只需在O(k log k)对它们进行排序。因此,根据需要,总复杂度为O(n + k log k)