输出前m大的数(快排)

描述

给定一个数组,统计前m大的数并且把这k个数从大到小输出。

输入

第一行包含一个整数n,表示数组的大小。n < 100000。
第二行包含n个整数,表示数组的元素,整数之间以一个空格分开。每个整数的绝对值不超过100000000。
第三行包含一个整数m。m< n。

输出

从大到小输出前m大的数,每个数一行。

样例输入

10
4 5 6 9 8 7 1 2 3 0
5

样例输出

9
8
7
6
5
为了降低时间复杂度,运用快排求该问题。
1)先找到那m大的值
2)对这m大的值进行排序

如何找m大的值:
快排,找取中间值,比中间值大的在右边,小的在左边。
若右半部分正好等于m,直接返回,继续2)。
若右半部分大于m,则继续调用1),在右半部分中寻找m大的数
若右半部分小于m个,则需在左半部分需要剩下的数。

#include<iostream>
#include<cstdio>
#define p 100001
using namespace std;
int ans=0,n,a[p],b[p],m;
void swap(int &m,int &n){
    int temp=m;
    m=n;
    n=temp;
}
void kuaipai(int s,int e,int m){//快速排序
    if(s>=e)
        return;
    int k=a[s];//选定的“中间”值
    int low=s,high=e;
    while(low!=high){
        while(low<high&&a[high]>=k)
            high--;
        swap(a[low],a[high]);//若后面值比中间值小,要放在后面,可与后面的a[high]调换
        while(low<high&&a[low]<=k)
            low++;
        swap(a[low],a[high]);//全部处理完后,low=high,并且“中间值”的位置为a[low]
    }
    if(e-low+1==m)
            return;
        else if(e-low+1>m)
            kuaipai(low+1,e,m);
        else
            kuaipai(s,low-1,m-e+low-1);

}
void kuai(int s,int e){
    if(s>=e)
        return;
    int k=a[s];
    int low=s,high=e;
    while(low<high){
        while(low<high&&a[high]>=k)
            high--;
        swap(a[low],a[high]);
        while(low<high&&a[low]<=k)
            low++;
        swap(a[low],a[high]);
    }
    kuai(s,low);
    kuai(low+1,e);

}
int main()
{
        scanf("%d",&n);
        for(int i=0;i<n;++i)
            scanf("%d",&a[i]);
        scanf("%d",&m);
        kuaipai(0,n-1,m);
        kuai(n-1-m,n-1);
        for(int i=n-1;i>n-1-m;i--){
            printf("%d\n",a[i]);
        }
}

猜你喜欢

转载自blog.csdn.net/lijunyan5/article/details/81483941