今天做题遇到了一个这样的题:
链接:https://ac.nowcoder.com/acm/problem/207028
来源:牛客网
第k小数
时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
给你一个长度为n的序列,求序列中第k小数的多少。
输入描述:
多组输入,第一行读入一个整数T表示有T组数据。
每组数据占两行,第一行为两个整数n,k,表示数列长度和k。
第二行为n个用空格隔开的整数。
输出描述:
对于每组数据,输出它的第k小数是多少。
每组数据之间用空格隔开
示例1
输入
2
5 2
1 4 2 3 4
3 3
3 2 1
输出
2
3
备注:
t ≤ 10, 1 ≤ n ≤ 5×10^6, k ≤ n,数列里每个数都在int范围内
由于输入比较多,请使用快读读取。
例如:
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
自己太垃圾了,想了一会儿不知道该怎么做,瞅了一眼题解,有位大佬就是用了nth_element()
函数来解决了。顿时觉得自己孤陋寡闻了。
nth_element()
-
头文件:
#include<algorithm>
-
nth_element
是部分排序算法,它重排[first, last)
中元素,使得:nth
所指向的元素被更改为假如[first, last)
已排序则该位置会出现的元素。- 这个新的
nth
元素前的所有元素小于或等于新的nth
元素后的所有元素。
-
参数
- first, last - 定义待排序范围的随机访问迭代器
- nth - 定义排序划分点的随机访问迭代器
- policy - 所用的执行策略。细节见执行策略。
- comp - 比较函数对象(即满足比较 (Compare) 概念的对象),若第一参数小于(即先序于)第二参数则返回 true 。
比较函数的签名应等价于如下:
bool cmp(const Type1 &a, const Type2 &b);
-
注意:他是没有返回值的,并且不能保证n位置两边是有序的。
示例:
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int a[] = {5,6,8,7,4,3,2,0,1};
//0,1,2,3,4,5,6,7,8
nth_element(a,a+1,a+10);
cout << "[*]The third largest num:" << a[2] << endl;
cout << "[*]Array a:" << endl;
for(int i=0;i<10;i++)
cout << a[i] << ' ';
cout << endl;
return 0;
}
/*
[*]The third largest num:2
[*]Array a:
0 1 2 5 4 3 6 7 8 9
*/
回到题目:
思路:利用快读输入数据,再用nth_element()
函数找到第k小数就可。
代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 5e6+5;
int arr[maxn];
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
int main() {
int T;
T = read();
while(T--) {
int n,k;
n = read();
k = read();
for(int i=0;i<n;i++)
arr[i] = read();
nth_element(arr,arr+k-1,arr+n);
printf("%d
",arr[k-1]);
}
return 0;
}