我正在尝试将算法的运行时间降低到O(n + klogk),但我似乎无法做到这一点。我通过使用最小堆获得O(n + nlogk)。基本算法如下:
构建给定数组的前k个元素(arr [0]到arr [k-1])的Min Heap MH。 O(k)的
对于每个元素,在第k个元素(arr [k]到arr [n-1])之后,将它与MH的根进行比较。 O((N-K)的logK)
最后,MH有k个最大元素,MH的根是第k个最大元素。调用extractMin k次以获得O(klogk)。
这得到O(k +(n-k)Logk + kLogk),等于O(k + nlogk)。但我需要O(n + klogk)。
我不知道如何使用min heap更快地完成它。有什么建议?
答案 0 :(得分:2)
使用这种min-heap方法的问题是你必须不断处理整个数组的其余部分,在n
前面给你一个log k
因子。
通过使用类似于分而治之的策略,有一种方法可以减少实际提取第一个k
元素所做的工作快速排序这会以指数方式减少必须处理的数组部分。
L
,右侧有R
。k == L
那么我们就完成了:数组中的第一个k
元素是最小的。k < L
然后从1继续,则仅处理左侧分区。k > L
然后从1继续,则使用新值k' = k - L
处理正确的分区。 如果上面的描述含糊不清(编辑:它可能是),这个方法是众所周知的,并且有很多来源(SO here's one,带代码)。
假设在平均情况下,枢轴近似地将数组分成两个相等的一半(这也是理想情况),时间复杂度递归关系由T(m) = T(m/2) + O(m)
给出,这意味着上述算法<强> O(n)
强>
在此之后,数组的第一个k
元素是无序的,因此只需在O(k log k)
对它们进行排序。因此,根据需要,总复杂度为O(n + k log k)
。