任务描述
本关任务:
独立完成中值问题。
相关知识
为了完成本关任务,你需要掌握:分治法。
题目
输入 n 个整数和一个一个正整数k (1<=k<=n),输出这些整数从小到大排序后的第k个(例如,k=1就是最小值)。n<=10
7
分析
备注(在数据结构算法中,解决问题的方法有很多,但是,请转变一个观念。不是达到目的就可以了。要考虑时间效率。如果在最短的时间内完成任务。)
选择第k大的数,最容易想到的方法是先排序,然后直接输出下标为k-1的元素(别忘了C语言中数组下标从0开始),但10
7
的规模即使对于O(nlogn)的算法来说较大。有没有更快的方法呢?
答案是肯定有的。假设在快速排序的“划分”结束后,数组A[l···r]被分成了A[l···q]和A[q,r],则可以根据左边的元素个数q-l+1和 k的大小关系只在左边或者右边递归求解。
时间复杂度
可以证明,在期望意义下,程序的时间复杂度为O(n)。
快排科普
快速排序的时间复杂度为:最坏情况O(n
2
);平均情况O(nlogn),但实践中几乎不可能达到最坏情况,效率非常高。根据快速排序思想,可以在平均O(n)时间内选出数组中第 k 大的元素。
编程要求
根据提示,在右侧编辑器补充代码,选出序列中第k大的元素。
测试说明
输入数据:
三行。第一行输入数字n。(有n个数待排序);
第二行。有n个数。(待排序的n个数)。
第三行,k值。
输出数据:
一个数。为n给数中第k位的数(数据从小到大)。
平台会对你编写的代码进行测试:
测试输入:
4
3 1 2 4
3
预期输出:
3
测试输入:
7
4 7 5 3 6 2 1
4
预期输出:
4
开始你的任务吧,祝你成功!
#include<stdio.h>
int partion(int a[],int l,int r)
{
int p,j,temp;
int s=l;
int g;
p = r;
// p = a[length];
for (j = l; j<=p; j++)
{
while (1)
{
if (a[s] <a[p])
{
s = s + 1;
//把s移到大于准值的位置
}
else
break;
}
if (a[j] <=a[p]&&j>s)
{
temp = a[s];
a[s] = a[j];
a[j] = temp;
//检测到小于准值的位置进行交换
}
}
g=s+1;
//对最终位置进行标记
// temp = a[s];
// a[s] = a[p];
//a[p] = temp;
return g;
}
int main()
{
int b[100000],i,l1,r1,k1=-1;
int n,k,h;
scanf("%d", &n);
l1=0,r1=n-1;
for(i=0; i<n; i++)
scanf("%d", &b[i]);
scanf("%d",&k);
while (1)
{
h=k1;
k1= partion(b,l1,r1);
if(k1==k||h==k1)
{
printf("%d",b[k-1]);
for(int i=0; i<n; i++) printf(" %d",b[i]);
break;
}
//break;
if(k1>k)
{
r1=k1-2;
continue;
}
if(k1<k)
{
l1=k1-1;
}
}
return 0;
}