可能重复:
How to find the kth largest element in an unsorted array of length n in O(n)?
我目前正坐在课程作业面前。 任务是找到数组中的第n个最小元素。 (没有排序!)
我试图理解BFPRT算法,但是从我得到的算法来看,只有你想要计算中值而不是“第n个最小”元素才有用。
我的另一个想法是通过将较小/较大的节点附加到根节点的左/右来将数组转换为树。但我不确定这是否算作排序。 为了加快这个速度,我可以在每个节点中存储子节点的数量。
完整的分配还包括算法必须是递归的。 还有提示考虑其他数据结构。
您如何看待我将阵列转换为平衡树的想法?
我可能错过了其他任何选项吗?
编辑:我查看了各种类似的问题,但未能完全理解答案/将其应用于我的具体任务。
答案 0 :(得分:15)
解决此问题的传统方法(订单统计问题)让人联想到quicksort。假设您正在寻找 k '最小元素。选择一个(随机)pivot元素并将其余元素分成两组(不对两组进行排序): L 包含小于或等于pivot元素的所有元素(pivot元素本身除外) ), G 包含大于pivot元素的所有元素。 L 有多大?如果它包含 k - 1 元素,则pivot元素必须是 k '最小元素,并且您已完成。如果 L 包含多个 k - 1 元素,则 k '最小元素必须位于 L ;否则,它在 G 中。现在,将相同的算法应用于 L 或 G (如果您需要使用 G ,则必须调整 k 因为你不再寻找 k ' G 的最小元素,而是整个 k '最小元素。/ p>
此算法在预期的 O(n)时间内运行;然而,在最坏的情况下,存在对算法的巧妙修改,以保证 O(n)时间。
编辑:正如@Ishtar指出的那样,“聪明的修改”是 BFPRT算法。其核心思想是确保您永远不会选择错误的枢轴元素,这样两个分区 L 和 G 不会变得太不平衡。只要可以保证一个分区永远不会超过 c 倍于其他分区(对于某些任意但固定的 c ),运行时间将为< EM> O(n)的
答案 1 :(得分:3)
理论上有一种非常复杂的算法在O(n)中运行。实际上它有点慢。请看一下这个链接:link。还有关于此问题的维基百科条目:wikilink
修改强>
一种解决问题的简单伪码算法:
k =第k个元素是我们正在寻找的
FindKthSmallest(Array, k)
pivot = some pivot element of the array.
L = Set of all elements smaller than pivot in Array
R = Set of all elements greater than pivot in Array
if |L| > k FindKthSmalles(L, k)
else if(|L|+1 == k) return pivot
else return FindKthSmallest(R, k-|L|+1)
答案 2 :(得分:0)
我喜欢这里的锦标赛算法 - 它非常直观且易于理解。