在许多题目中都会出现寻找第k大的数的类似问题,最简单的做法就是先排序在找位置就可以找到第k大的数,但是排序的做法显然不能满足我们的要求,排序的时间复杂度是O(nlogn),不够快,我们一般可以用快速排序的思想,用O(n)的时间内就可以找到第k大的数,这里我们只讲解C++ STL的函数nth_element。

先看一下STL

template<class _RanIt, class _Pr> inline
    void nth_element(_RanIt _First, _RanIt _Nth, _RanIt _Last, _Pr _Pred)
 
template<class _RanIt> inline
	void nth_element(_RanIt _First, _RanIt _Nth, _RanIt _Last)

从STL中可以看出nth_element可以带3个或者4个参数,第一个就是寻找的数组或者容器开始的位置,第二个就是寻找的第k大的数,第三个就是寻找的数字或者容器结束的位置。

如果用于数组:

#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{
    int a[10] = { 8, 9, 1, 2, 4, 3, 5, 6, 7, 10 };
    nth_element(a, a + 5, a + 10, std::greater<int>());
    cout << "数组中的中间元素是" << a[5] << endl;
    nth_element(a, a, a + 10, std::greater<int>());
    cout << "数组中第1大元素为" << a[0] << endl;
    nth_element(a, a + 1, a + 10, std::greater<int>());
    cout << "数组中第2大元素是" << a[1] << endl;
}

如果用于容器vector:

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
int main()
{
	vector<int> v;
	int n,a;
	cin>>n;
	for(int i=0;i<n;i++)	cin>>a,v.pb(a);
	for(int i=0;i<n;i++)	cout<<v[i]<<' ';
	cout<<endl;
	vector<int>::iterator it;
	for(it=v.begin();it<v.end();it++)	cout<<*it<<' ';
	cout<<endl;
	nth_element(v.begin(),v.begin(),v.end());
	for(it=v.begin();it<v.end();it++)	cout<<*it<<' ';
	return 0;
}

如果加上第4个参数,那么就是要进行自定义查找了,自定义的查找方式。

比如对结构体进行自定义的方式的查找

struct node
{
	int ct,id;
}t[N*10];
int cmp(node a,node b)
{
	if(a.ct==b.ct)	return a.id<b.id;
	else	return a.ct<b.ct;
}

nth_element(t+1,t+k,t+n+1,cmp);