我经常发现自己遇到这个问题:给定一个序列,找到k-最小的元素。问题并不那么难,但我正在寻找的是一种“惯用”的方式,这是安全的(几个错误的地方)并且很好地沟通意图。所以最终做的是对序列进行排序,然后取第一个k元素:
std::sort(container.begin(),container.end());
std::vector<T> k_smallest(container.begin(),container.begin() + k);
在我看来这既安全又易于理解,但这里的复杂性是nlogn + k,而不仅仅是n。 你们是如何做到这一点的,是否有一种自觉的方式(使用一些不起眼的功能)可以提供最佳的复杂性而无需重新实现轮子
答案 0 :(得分:16)
std::nth_element() - 平均线性复杂度。
nth_element
是一种重新排列元素的部分排序算法 [first,last]这样:
- 如果[first,last]已排序,则第n个指向的元素将更改为该位置中出现的任何元素。
- 这个新的第n个元素之前的所有元素都小于或等于新的第n个元素之后的元素。
答案 1 :(得分:7)
您可能需要查看partial_sort()
它很容易理解,不需要额外的工作,并且如果你只关心第k个元素,那么预期会更好[或者至少不会更差] sort()
。
为获得最佳性能 - 您可能希望使用selection algorithm,但需要更多工作。
答案 2 :(得分:0)
<强>步骤:强>
<强>复杂度:强> O(n)最坏情况
<强>步骤:强>
您可以使用priorty queue的方法(c'tor,top,pop)来了解后面的算法。
<强>复杂度:强> O(n + k * log(n))最坏情况