P1923 求第 k 小的数

Posted 年轻人不讲码德

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1923 求第 k 小的数相关的知识,希望对你有一定的参考价值。

P1923 求第 k 小的数

题目如图所示 原本是在PTA上遇到这个题的,但是PTA没有搜索功能

在这里插入图片描述

思路:分治+快读(时间复杂度O(n))

先进行算法时间复杂度的分析,这道题目是不能直接用快速排序的,快速排序的平均复杂度为O(nlogn),但是在序列高度有序的情况下快速排序的时间复杂度O(n2),这道题的时间限制是1s(PTA上的时间卡的更紧,只有170ms,但是PTA的数据规模只有1e6),计算机1s内最多进行1e9次运算,快速排序在最坏的情况下要进行2.5*10^12次运算。也就是说用快速排序百分百会超时。

到这里我们就不用考虑用排序来解这道题,而采用分治策略,每次分治后序列的长度都会减少,时间复杂度成线性变化,总时间复杂度为O(n)。

这里附上AC代码

#include<stdio.h>
#define INF 5000000
int a[INF+5],k;
void quicksort(int l,int r)
{
	int i=l,j=r;
	int mid=a[i];//设置关键字
	if(l<r)
	{
		while(i<j)//把比关键字小的扔到关键字左边,把比关键字大的扔到关键字右边(此操作与快排类似)
		{
			while(i<j&&a[j]>=mid) j--;
			if(i<j) a[i]=a[j],i++;
			while(i<j&&a[i]<=mid) i++;
			if(i<j) a[j]=a[i],j--;
		}
		a[i]=mid;//关键字的最终位置
		if(i>k) quicksort(l,i-1);//如果关键字在k的左边,那就舍弃右边的序列,对关键字左边的序列进行分治
		else if(i<k) quicksort(i+1,r); //同上
	}
}
int read()//由于getchar读取的效率比scanf更高,这里用读取字符的方式代替scanf进行输入
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-f;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+ch-'0';//位运算的效率比乘法更高,所以这里将x*10改为(x<<1)+(x<<3)
		ch=getchar();
	}
	return x*f;
}
int main (void)
{
	int n;
	n=read();
	k=read();
	for(int i=0;i<n;i++)
	a[i]=read();//快读
	quicksort(0,n-1);
	printf("%d",a[k]);
}

测评结果

在这里插入图片描述

以上是关于P1923 求第 k 小的数的主要内容,如果未能解决你的问题,请参考以下文章

P1923 求第 k 小的数

P1923 求第 k 小的数

P1923 求第 k 小的数

P1923 求第 k 小的数

P1923 深基9.例4求第 k 小的数

快排划分思想的应用-求第k大数或者第k小的数(求前k大数或者前k小的数)