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 小的数的主要内容,如果未能解决你的问题,请参考以下文章