找到m个最大数字

时间:2014-10-29 15:27:39

标签: algorithm sorting heap

这是Cormen文本中的问题,但我想看看是否还有其他解决方案。

给定一个具有n个不同数字的数组,您需要在数组中找到m个最大的数组,并且具有 他们按排序顺序。假设n和m很大,但生长方式不同。特别是,你需要 在下面考虑m = t * n的情况,其中t是一个小数,比如0.1,然后是 可能性m =√n。

本书中给出的解决方案提供了3种选择:

  1. 对数组进行排序并返回顶部的m-long段
  2. 将数组转换为最大堆并提取m个元素
  3. 选择第m个最大数字,对数组进行分区,然后对较大条目的分段进行排序。
  4. 这些都是有道理的,而且它们各有利弊,但我想知道,还有另外一种方法吗?它不一定更好或更快,我只是想知道这是否是更多解决方案的常见问题,或者我们是否仅限于这三种选择。

2 个答案:

答案 0 :(得分:3)

您提到的三种方法的时间复杂性如下:

  1. O(n log n)
  2. O(n + m log n)
  3. O(n + m log m)
  4. 因此,在渐近复杂度方面,选项(3)肯定比其他选项更好,因为m <= n。当m很小时,(2)和(3)之间的差异很小,几乎没有实际影响。

    至于解决问题的其他方法,你可以有很多方法,所以在这方面问题有点差。我能想到的另一种方法是实际上简单和高效,如下所示。

    1. 将n列表中的前m个数字提取到数组中,然后对其进行排序。
    2. 重复抓取列表中的下一个数字并将其插入数组中的正确位置,将所有较小的数字移到一个并将其中一个移出。
    3. 如果m非常小,我只会这样做。如果你有一个最大堆实现并且工作得很好,那么原始列表中的选项(2)也非常容易实现。

答案 1 :(得分:3)

一种不同的方法。

取前m个数字,然后将它们变成最小堆。运行数组,如果其值超过前m的min,则提取min值并插入新值。当您到达数组的末尾时,您可以将元素提取到数组中并反转它。

此版本的最差情况是O(n log(m))将其置于第一种和第二种效率方法之间。

平均情况更有趣。平均只有O(m log(n/m))个元素将通过第一个比较测试,每次O(log(m))工作,所以你得到O(n + m log(n/m) log(m))工作,这将它放在第二个和第三个方法之间。 如果nm多出几个数量级,那么O(n)块占主导地位,而第三种方法中的O(n)中位数选择具有比这种方法中每个元素的一个比较更糟的常数,所以在这种情况下,这实际上是最快的!