【问题标题】:Finding n-th smallest element in an array [duplicate]查找数组中的第 n 个最小元素 [重复]
【发布时间】:2011-08-29 15:53:55
【问题描述】:

可能重复:
How to find the kth largest element in an unsorted array of length n in O(n)?

我目前正在做课程作业。 任务是在数组中找到第 n 个最小的元素。 (不排序!)

我试图了解 BFPRT 算法,但据我所知,它仅在您想计算中位数而不是“第 n 个最小”元素时才有用。

我的另一个想法是通过将较小/较大的节点附加到根节点的左/右来将数组转换为树。但是,我不确定这是否算作排序。 为了加快速度,我可以在每个节点中存储子节点的数量。

完整的分配还包括算法必须是递归的。 还有考虑其他数据结构的提示。

您对我将数组转换为平衡树的想法有何看法?

还有其他我可能错过的选项吗?

编辑:我查看了各种类似的问题,但无法完全理解答案/将它们应用于我的特定任务。

【问题讨论】:

  • 我发现有关数据结构的提示令人惊讶。解决这个问题的典型算法不需要额外的数据结构。

标签: algorithm


【解决方案1】:

解决这个问题的传统方法(顺序统计问题)让人想起快速排序。假设您正在寻找第 k 个最小的元素。选择一个(随机)枢轴元素并将剩余元素分成两组(不对两组进行排序): L 包含小于或等于枢轴元素的所有元素(枢轴元素本身除外) ),而 G 包含所有大于枢轴元素的元素。 L 有多大?如果它正好包含 k - 1 个元素,那么枢轴元素必须是第 k 个最小的元素,你就完成了。如果L包含多于k - 1个元素,则k的最小元素必须在L中;否则,它在 G 中。现在,对 L 或 G 应用相同的算法(如果需要使用 G,则必须调整 k 因为您不再寻找 G 中第 k 个最小的元素,而是寻找整体上第 k 个最小的元素)。

此算法在预期的 O(n) 时间内运行;但是,算法有一个巧妙的修改,可以在最坏的情况下保证 O(n) 时间。

编辑:正如@Ishtar 指出的那样,“聪明的修改”是 BFPRT 算法。它的核心思想是确保你永远不会选择一个糟糕的枢轴元素,这样两个分区 L 和 G 就不会变得太不平衡。只要可以保证一个分区永远不会比另一个分区大 c 倍(对于一些任意但固定的 c),运行时间将是 c em>O(n).

【讨论】:

【解决方案2】:

理论上有一个相当复杂的算法在 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)

【讨论】:

  • 我已经查看了您的两个链接。 PowerPoint 幻灯片非常好,但我不明白那里写的所有内容。此外,所描述的算法是 BFPRT 算法,据我所知,它只意味着返回数组的中位数,而不是第 n 个最小的。
  • @Martin Klepsch - 您可以轻松地从该算法中获得第 n 个最小的项目。我很快就会编辑我的帖子。
【解决方案3】:

我喜欢这里的锦标赛算法——它非常直观且易于理解。

http://en.wikipedia.org/wiki/Tournament_selection

【讨论】:

    猜你喜欢
    • 2018-09-01
    • 2015-12-02
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-13
    相关资源
    最近更新 更多