之前partial_sort有讲述了如果从一个无序序列中快速获得top m的所有有序数列m个。我们也常常会遇到这样的问题:如何在一个乱序的序列集合中,找到第K大的或者排名第K的那个元素?或者找到前K个排名的元素,但是这K个数之间的顺序对我们来说并不重要。比如篮球比赛中总胜利场数最多的20支球队进入总决赛,而这20支球队之前各自胜利多少的排名并不重要,因为决赛要重新比。 这个问题我们同样可以用排序来解决,最简单的方法也是将所有序列集合进行排序,直接取第K个位置上的数即可,但是这里我们要介绍一种线性时间复杂度(O(N))的算法:nth_element 该算法也来自于STL的算法库,在研究STL源码时看到的,瞬间眼前一亮,这里分享出来。
nth_element算法将重新排列区间[first, last)的序列元素, 使得第k个元素位置的元素在最终算法执行完毕后和整个区间完全排序后该位置元素具有相同的值,也就是说完全排序后该位置上出现的值,将会在该算法执行完成后依然在该位置。但是该算法并不保证位于第K个元素两边的区间的元素有序,只保证[ k, last)区间内没有元素不小于第K个元素位置的值。 看上去和我们之前讲解的partial_sort做的事情很像,但是他们有一个很大的区别在于。nth_element对于除第K位置的元素之外的区间的顺序不做保证,而partial_sort排序后前m个数的子区间是有序的。正因为如此在需要无序的前top k个值时 nth_element相对于partial_sort要更快。