【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,我能够快速地说出这些数字里面第 大的数字。”

Input

第1行 两个整数N, K以空格隔开;

第2行 有N个整数(可出现相同数字,均为随机生成),同样以空格隔开。

0 < n ≤ 5*10^6 , 0 < k ≤ n

1 ≤ xi ≤ 10^8

Output

输出第 大的数字。

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
原创粉丝点击