Luogu P1923 求第 k 小的数

link

求第 k 小的数

题目描述

输入 \(n\)\(1 \le n < 5000000\)\(n\) 为奇数)个数字 \(a_i\)\(1 \le a_i < {10}^9\)),输出这些数字的第 \(k\) 小的数。最小的数是第 \(0\) 小。

请尽量不要使用 nth_element 来写本题,因为本题的重点在于练习分治算法。

输入格式

输出格式

样例 #1

样例输入 #1

5 1
4 3 2 1 5

样例输出 #1

2

三个解法:

  • 先sort一遍数组,再找下标k的元素。(TLE警告)

  • 借用快排分治思想,将数组一分为二,找k在左边还是右边。

  • 在C++的库STL中,有一个神奇的函数nth_element,顾名思义,找到数组的第n大的数,具体用法详见OI-Wiki(个人推荐C++自学网站,内容齐全,教程详细,简单涉及Python)

这道题可以作为快排的模版题因为递归函数部分与快排几乎一毛一样。

#include<bits/stdc++.h>
using namespace std;
int n,k,ans;
int a[5000005];
void findk(int a[],int l,int r)
{
	if(l==r)
	{
		ans=a[l];
		return ;
	}
	int i=l,j=r,flag=a[(l+r)/2];
	do{
		while(a[i]<flag)
			i++;
		while(a[j]>flag)
			j--;
		if(i<=j)
		{
			swap(a[i],a[j]);
			i++,j--;
		}
	}while(i<=j);
	if(k<=j) findk(a,l,j);
	else if(k>=i) findk(a,i,r);
	else findk(a,j+1,i-1);
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>k;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
	}
	findk(a,0,n-1);
	cout<<ans<<endl;
	return 0;
}

posted @ 2024-01-25 21:57  j1hx  阅读(30)  评论(0)    收藏  举报