【O(n)求第K大】ACdream 1099 瑶瑶的第K大
来源:互联网 发布:代刷分站域名设置 编辑:程序博客网 时间:2024/04/29 20:56
题目链接:http://acdream.info/problem?pid=1099
瑶瑶的第K大
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 512000/256000 KB (Java/Others)
Problem Description
一天,萌萌的妹子--瑶瑶(tsyao)很无聊,就来找你玩。可是你们都不知道玩什么。。。尴尬了一阵子,机智的瑶瑶就提议:“这样吧,你说N个整数xi,然后在随意说一个数字k,我能够快速地说出这些数字里面第 k 大的数字。”
Input
第1行 两个整数N, K以空格隔开;
第2行 有N个整数(可出现相同数字,均为随机生成),同样以空格隔开。
0 < n ≤ 5*10^6 , 0 < k ≤ n
1 ≤ xi ≤ 10^8
Output
输出第 k 大的数字。
Sample Input
5 25 4 1 3 1
Sample Output
4
Hint
如2,2,1中三个数字中第一大数字为2,第二大数字也为2,第三大数字为1 。
利用快排思想
一个简单的寻找第k大的算法,再加上一个十(sang)分(xin)炫(bing)酷(kuang)的读入优化,就解决了..
无读入优化版
/** this code is made by f_xuan* Problem: 1099* Verdict: Accepted* Submission Date: 2014-06-19 16:02:49* Time: 4964 MS* Memory: 21208 KB*/#include<cstdio>#include<stdlib.h>#include <iostream>using namespace std;#define N 5000010int a[N];int partition(int l,int r){ swap(a[(l+r)>>1],a[r]);//取中间值下标的值为分界线 int x = a[r]; int i = l - 1;//i用来记录比x小的数下标 for(int j = l ; j < r ; j ++) { if(a[j] < x)//比x小的数放到左边 { i ++; swap(a[i],a[j]);//交换 } } swap(a[i+1],a[r]);//由于从l到i都是比x小的数,那么下标i+1就应该是分界的x即a[r] return i + 1;} int select(int k,int l,int r)//找出数组中第K大元素{ while(l!=r){ int q = partition(l,r); int t = r - q + 1;//右边数的个数 if(k == t) return a[q];//k==t那么a[q]就是答案 else if(k > t) { k=k-t,r=q-1;//在左边进行查找,注意这里就需要查找第k-t大数了 } else { l=q+1;//在右边进行查找 } } if(l == r) return a[l];//数组中只有一个数} int main(void){ int n,k; cin>>n>>k; int i; for(i=0;i<n;++i){ scanf("%d",&a[i]); } int r = select( k, 0, n-1); cout<<r<<endl; return 0;}
标程
/** this code is made by tsyao* Problem: 1099* Verdict: Accepted* Submission Date: 2014-06-19 16:04:32* Time: 3852 MS* Memory: 40148 KB*/#include<cstdio>#include<cstring>#include<algorithm>using namespace std ; const int maxn = 10000000 ;int n , k , op ;int a[maxn] ; int read() { int tmp = 0 ; char x ; while(1) { x = getchar() ; if(x >= '0' && x <= '9') tmp = tmp*10 + x - '0' ; else break ; } return tmp ;} int find(int L,int R,int kth) { if(L == R-1) return a[L] ; int mid_num = a[(L+R)>>1]; int l = L , r = R ; while(l < r-1) { while(l < r && a[l] > mid_num) l++ ; while(l < r && a[r-1] < mid_num) r-- ; if(l < r-1) swap(a[l] , a[r-1]) ; if(l < r-1) {l++ ; r-- ;} } if(r-l) { if(a[l] > mid_num) l++ ; else r-- ; } if(r-L >= kth) return find(L , r , kth) ; else return find(r , R , kth-(r-L)) ;} int main() { scanf("%d%d\n",&n,&k) ; for(int i = 0 ; i < n ; i++) a[i] = read() ; int tmp = find(0 , n , k) ; printf("%d\n",tmp) ; return 0 ;}
0 0
- 【O(n)求第K大】ACdream 1099 瑶瑶的第K大
- 【ACdream OJ 1099 - 瑶瑶的第K大 (输入优化+手写O(n)快排)】
- ACdream OJ 1099 瑶瑶的第K大
- ACdream 1099 瑶瑶的第K大
- ACdream 1099 - 瑶瑶的第K大
- ACdream 1099 瑶瑶的第K大
- 瑶瑶的第K大 ACdream-1099
- ACdream OJ 1099 瑶瑶的第K大 --分治+IO优化 - whatbeg
- 求第k大
- n个数求第k大
- O(n)查找第k小(大)的数
- 寻找第k小的元素或者第k大的元素 -- O(n)
- 求n个数中第k大的数、前K大的数、快速排序
- ACdream群赛14---A题瑶瑶的第K大
- 第K小的数 快速排序 选择前K大O(n)
- 求第K大源码
- 求数组第K大
- 求第K大的数~~
- VSFTP安装配置
- Android 开发笔记——通过 Intent 传递类对象
- 【树状数组】 HDOJ 3743 Frosh Week
- 局部变量的位置分配
- Select top from datatable
- 【O(n)求第K大】ACdream 1099 瑶瑶的第K大
- linux下编译动态链接库的一个小例子
- 活下去,是因为要去捍卫一个人
- BaseExpandableListAdapter的用法
- 汉诺塔的实现 作者:皮特 时间:2012-08-20 02:15:55
- 你说呢明知你不在还是会问
- C语言操作MYSQL------基于VC6.0 & VS2010
- 64位 Linux 编译32位应用程序
- 判断一个字符串里是否包含了另一个字符串