Top K

TOP K 时间缩减

1003.寻找第k大数字(numberk)

Time Limit: 10sec Memory Limit:256MB
Description

经过长时间的筹备工作,在Jourk,Ronny,Plipala,阿长,阿沈等人的努力下,DM实验室建立起自己的系列网站,其中包括三个大板块:DMOJ首页、DMOJ论坛、DMOJ博客。
作为一个大型的网站,数据的加工处理需要用到很多算法系统模块,通过这些模块对系统主数据库进行修改。因此,在构建DMOJ系列网站的过程中,编写了一个庞大的数据统计系统,其中包括一个寻找第k大数字的模块,对于一个数据库来说,这样一个模块的重要性不容置疑。但是,由于在修改网站的过程中,这个模块被不慎删掉了,DMOJ找到了聪明的你,希望你能帮DMOJ重写这个模块。
对于输入数据,你将按数据要求找出n个数字中的第k大数字。
关于第k大数字的解释:对于一个数字序列,计算该数字序列第k大数字,一种可行但效率不高的方法是,首先剔除数字序列中重复的数字,然后通过某种排序算法,获得剔除重复数字后的数字序列从大到小排序的数字序列,然后取从大到小排序的数字序列的第k位的数字。从另一个角度,题目中的第k大数字即是不计入数字序列中数字重复出现的部分,对于数字重复出现的情况,应该认为该数字只出现一次。
现在请聪明的你尝试设计一种可行且效率更高的方法来解决这个问题。
不能使用algorithm的排序函数, 这道题TA会观赏大家代码,请重新提交

不用algorithm头文件,有种方法可以做到2.62s, 希望大家能想办法做得更快!

PS:

1、做了这个题以后面试遇到人家问怎么找数组里面的中位数就不要再说什么先排序然后找中间那个数了

2、这个题网上有很多解法,也有人分析每种解法的时间复杂度,有兴趣了解多少就多少

3、如果你了解了多种解法,那么请分析,这些解法分别在什么情况下会比较好?

比如求中位数,哪种解法比较好?再比如求最大值,哪种方法比较好?

Input
输入数据一共有三行。
第一行有一个正整数n(n<=10000000),表示一共给出多少个数字。
第二行有一个正整数k(k<=10000000),表示要求你找出第k大数字。
第三行有n个整数,给出n个数字。对于每个整数i,均满足-10000000<=i<=10000000。
Output
输出文件共一行,包含一个整数,表示n个数字中第k大数字是多少。

Sample Input
Copy sample input to clipboard
3
2
2006 2007 2008

Sample Output
2007
Hint
不能使用algorithm的sort/qsort函数————
#include
#include
#include
#define Max 20000001
#define M 10000001
using namespace std;

int a[Max]; // 
int b[M];

int part(int a[], int low, int high, int K, int num)
{
    if(low >= high){return(10000001);}
    int f = low, l = high, k = a[f];
    while (f < l) {
        while(f < l && a[l] >= k){l--;}
        a[f] = a[l];
        while(f < l && a[f] <= k){f++;}
        a[l] = a[f];    
    }
    a[f] = k;
    if (num-f+1 == K) {
        return k;
    } 
    else if (num-f+1 > K) {
        part(a, f+1, high, K, num);
    }
    else {
        part(a, low, f-1, K-(num-f+1), f-1);
    }
}
int main() {
    int n, k, temp, count = 0, max = 0, min = M;
    cin >> n >> k; 
    for(int i = 1; i <= n; i++) {
        scanf("%d", &temp);
        if (!a[temp+10000000]) {
            a[temp+10000000] = 1;
            b[count++] = temp;
        }
    }
    count--;
    int ans = part(b, 0, count, k, count);
    if (ans != 10000001) {
        cout << ans << endl;
    }
    else {
        cout << b[count-k+1] << endl;
    }
}               
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值