搜索算法以查找列表中的k个最低值

Search Algorithm to find the k lowest values in a list

本文关键字:最低值 查找 列表 搜索算法      更新时间:2023-10-16

我有一个包含n双值的列表,我需要在该列表中找到k最低双值

  • kn小得多
  • 具有n双值的初始列表是随机排序的
  • 不需要对找到的k最低双精度值进行排序

你推荐什么算法

目前,我使用Quicksort对整个列表进行排序,然后从排序列表中取出第一个k元素。我认为应该有一个更快的算法。

感谢您的帮助

您可以对解决方案进行建模,以匹配Python标准库中的nlargest()代码。

  • 在maxheap上堆第一个k
  • 对剩余的n-k值进行迭代
  • 将每个元素与堆顶部的元素进行比较
  • 如果新值较低,请执行heapreplace操作(用新值替换最顶层的堆元素,然后向下筛选)

该算法的效率惊人。例如,当n=100000并且k=100时,对于随机排列的输入,比较的数量通常在106000左右。这仅略高于100000次比较,以找到一个最小值。而且,它对整个数据集进行的比较比完全快速排序少20倍。

对各种算法的相对强度进行了研究,总结如下:http://code.activestate.com/recipes/577573-compare-algorithms-for-heapqsmallest

您可以使用选择算法来找到第k个最低的元素,然后迭代并返回它以及低于它的所有元素。如果列表中可能包含重复的元素,则需要做更多的工作(确保您最终不会得到更多所需的元素)。
此解决方案为O(n)。选择算法在C++中实现为nth_element()

另一种选择是使用大小为k的最大堆,并在保持堆容纳所有k个最小元素的同时迭代元素。

for each element x:
   if (heap.size() < k):
      heap.add(x)
   else if x < heap.max():
      heap.pop()
      heap.add(x)

完成后,堆包含k个最小的元素。
此解决方案是O(nlogk)

看看C++标准库中的partial_sort算法。

您可以使用std::nth_element。这就是O(N)的复杂性,因为它不对元素进行排序,只是排列它们,使某个N下的每个元素都小于N。

您可以使用选择排序,它需要O(n)来选择第一个最低值。一旦我们在位置1上设置了这个最低值,我们就可以重新扫描数据集,找出第二个最低值。并且可以这样做,直到我们得到第k个最低值。通过这种方式,如果k足够小于n,那么我们将具有复杂性kn,它等价于O(n)。。。