P1923求第k小的数
第一、topk问题(采用快排优化后的topk,时间复杂度为O(n)),然后cin输入一直超时,最后换成了scanf函数AC
#include "bits/stdc++.h" using namespace std; int a[5000005]; void topk(int start,int end,int k) { int i = start; int j = end; int temp = a[start]; while(i < j){ while(i < j && a[j] >= temp) j--; while(i < j && a[i] <= temp) i++; if(i < j) swap(a[i],a[j]); } swap(a[i],a[start]); if(i == k)//如果找到了那个位置,则返回 return; else if(i > k)//如果左边的数的长度已经大于k了,那么第k小的一定在左边 topk(start,i - 1,k); else topk(i + 1,end,k);//如果右边的数的长度已经大于k了,那么第k小的一定在右边
}
int main()
{
int k,n; cin >> n >> k;
for(int i = 0;i < n;i++) scanf("%d",&a[i]);//注意这段代码,不能用cin,否则会超时
topk(0,n - 1,k);
cout << a[k] << endl;//直接打印a[k]
return 0;
}
第二、利用c++ STL中的nth_element()函数解决,该函数的语法是nth_element(a,a + k,a + n),a为数组名,a+k是把第k小的数放在第a[k]这个位置,a+n是这个数组的结束地址,c++STL中的函数一般都是左闭右开区间。(这个函数的原型也是快速排序的分治,时间复杂度为O(n))
#include "bits/stdc++.h" using namespace std; int a[5000005]; int main() { int n,k; cin >> n >> k; for(int i = 0;i < n;i++) scanf("%d",&a[i]); nth_element(a,a+k,a+n);//nth_element是stl中的一个库函数,该函数可以从某个序列中找到第 n 小的元素 K, //并将 K 移动到序列中第 n 的位置处。 //不仅如此,整个序列经过 nth_element () 函数处理后, //所有位于 K 之前的元素都比 K 小,所有位于 K 之后的元素都比 K 大。 cout << a[k] << endl; return 0; }
第三、采用快读优化后时间编程了0.2s,可见快读的重要性,代码如下:
#include "bits/stdc++.h" using namespace std; int a[5000005]; int read()//为什么要采用快读,因为字符输入会比整数输入快上很多 c++的cin和cout为了兼顾兼容性所以cin和cout时间很慢 { int x = 0; int code = 1;//表示符号的正负 char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') code = -1; ch = getchar();//接收掉负号以及不要要的其他符号 } while(ch >= '0' && ch <= '9'){ x = x * 10 + ch - '0'; ch = getchar(); } return code * x; } int main() { int n,k; n = read(); k = read(); for(int i = 0;i < n;i++) a[i] = read();//如果此处为cin的话,则会超时,所以我们可以采用快读的方式写入数字,快读不适用于大量的空格,单个读入字符要比读入数字快得多 nth_element(a,a+k,a+n); cout << a[k] << endl; return 0; }
本文来自博客园,作者:{scanner},转载请注明原文链接:{https://home.cnblogs.com/u/scannerkk/}