问题描述:
在N(0<N<100000)个数中,找出第K(0<k<100000)大的数。
例如:1,2,3,4,5,6,7,8,9 中第3大的数为 7。
输入:
输入有多组数据,处理到文件结束。
每组数据有两行,
第一行包括两个数,一个正整数N和一个正整数K,
第二行有N个正整数。
输出:
对于每组数据,输出一个数,表示第K大的数,并换行。
样例输入:
12 5
12 4 5 98 4 7 32 1 65 0 65 55 999
10 3
1 2 3 4 5 6 7 8 9 10
样例输出:
32
8
本题的思路可以是用数据结构中的堆来处理,时间复杂度为O(N*logK),
只需要建立大小为K的最小堆,堆顶就是第K大的数。
举个例子:假设N为10,K为3。第一步选取任意3个数,比如前3个,将这3个数建成最小的堆,
然后从第4个数开始,与堆顶的数比较,如果比堆顶的数小,那么这个数就不要,如果比堆顶的数要大,
则舍弃当前堆顶而将这个数作为新的堆顶,并在去维护堆,用同样的方法处理第5~10个数。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <stack>
#include <set>
#include <ctype.h>//isalpha,isdight,toupper
#include <map>
#include <sstream>
typedef long long ll;
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=101;
int h[100000],n;
void swap1(int a, int b)
{
int t;
t = h[a];
h[a] = h[b];
h[b] = t;
}
void siftdown(int i)
{
int t, flag = 0;
while(2*i <= n && flag == 0)
{
if(h[i] > h[2*i])
{
t = 2*i;
}
else
{
t = i;
}
if(2*i + 1 <= n)
{
if(h[t] > h[2*i + 1])
{
t = 2*i + 1;
}
}
if(t != i)
{
swap1(i, t);
i = t;
}
else
{
flag = 1;
}
}
}
void creat()
{
for(int i = n/2; i >= 1; i--)
{
siftdown(i);
}
}
int main()
{
int num, maxi, a[100000];
while(scanf("%d %d", &num, &maxi) != EOF)
{
n = maxi;
for(int i = 1; i <= num; i++)
{
scanf("%d", &a[i]);
h[i] = a[i];
}
creat();
for(int i = n + 1; i <= num; i++)
{
if(a[i] > h[1])
{
h[1] = a[i];
siftdown(1);
}
else
{
continue;
}
}
printf("%d\n", h[1]);
}
return 0;
}