题目描述
输入n(且n为奇数)个数字
(
),输出这些数字的第k小的数。最小的数是第0小。
请尽量不要使用nth_element来写本题,因为本题的重点在于练习分治算法。
输入格式
无
输出格式
无
输入输出样例
输入
5 1
4 3 2 1 5
输出
2
解题过程
我们首先解读一下题目的要求,即第一行输入两个数n和k,第二行输入n个数,输出n个数中第k大的数。
由于n的数量级不小,我们直接使用long类型存储,同样,a也使用long类型,而关于分治算法,我在此处使用的是快速排序。
然而,直接使用快速排序,仍然无法通过这道题,能够获得分数为60。
以下为普通快速排序的函数:
//排序函数
long Partition(long first, long last)
{
long i = first, j = last, temp = 0;
while (i < j)
{
//右侧扫描
while (i < j && arr[i] <= arr[j])
j--;
if (i < j) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
}
//左侧扫描
while (i < j && arr[i] <= arr[j])
i++;
if (i < j) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
j--;
}
}
return i;
}
//递归排序
void QuickSort(long first, long last)
{
if (first >= last)
return;
else {
long pivot = Partition(first, last);
QuickSort(first, pivot - 1);
QuickSort(pivot + 1, last);
}
}
对于这一情况,我们能够做的就是优化代码,由于快速排序是对所选定的轴值的两侧分别排序,我们可以通过判定语句,仅对包含位置为k的一侧进行排序,这样我们可以减少很多的运行时间。
优化后的代码如下:
void QuickSort(long first, long last, long k)
{
if (first >= last)
return;
else
{
long pivot = Partition(first, last);
if(pivot > k)
QuickSort(first, pivot - 1, k);
else if(pivot < k)
QuickSort(pivot + 1, last, k);
else
{
//输出后直接终止程序,防止重复打印
cout << arr[pivot];
exit(0);
}
}
}
然而,仅优化快速排序的算法还是没有办法通过这道题,甚至通过的测试点仍然没有变多,依旧超时了。
在那个时候我可以说是百思不得其解,算法已经优化了,怎么还是过不了,看题解后仍旧没有找到解决的方法。所以我直接润去百度,找有没有优化运算时间的方法。
"cin",这个我一直在用的东西,没有想到竟然是它的锅。检索后发现最有可能造成超时的是它后,我就改换了scanf来进行输入。嗯,不超时了,成功AC。
AC代码
#define _CRT_SECURE_NO_WARNINGS //visual studio 2022使用scanf需添加
#include<iostream>
#include<stdio.h>
using namespace std;
long Partition(long first, long last);
void QuickSort(long first, long last , long k);
long arr[5000005] = { 0 };
int main()
{
//输入n和k
long n = 0;
long k = 0;
scanf("%ld%ld", &n,&k);
//输入各个数
for (long i = 0; i < n; i++)
scanf("%ld",&arr[i]);
//到k的快速排序
QuickSort(0, n - 1, k);
//输出第k大的值
cout << arr[k];
return 0;
}
long Partition(long first, long last)
{
long i = first, j = last, temp = 0;
while (i < j)
{
//右侧扫描
while (i < j && arr[i] <= arr[j])
j--;
if (i < j) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
}
//左侧扫描
while (i < j && arr[i] <= arr[j])
i++;
if (i < j) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
j--;
}
}
return i;
}
void QuickSort(long first, long last, long k)
{
if (first >= last)
return;
else
{
long pivot = Partition(first, last);
if(pivot > k)
QuickSort(first, pivot - 1, k);
else if(pivot < k)
QuickSort(pivot + 1, last, k);
else
{
cout << arr[pivot];
exit(0);
}
}
}
文章介绍了一种优化的快速排序方法,用于寻找输入列表中第k大的数字,涉及分治策略和时间复杂度优化。作者在实践中遇到超时问题,通过更换输入方式解决。
514





