• 第k大的数


    问题描述:输入一组数,指定一个k,输出这组数里第k大的数。

    一般这种题目,第一想法是把整个数组先排序后,再选取第k位的数。
    但是这样做实际上浪费了大量的时间在排序上,我们只是要求第k大的数,并非要把整个数组排序完。

    利用快速排序算法的性质:每一趟排序,必有一个元素位于最终的位置,而且于此同时这个元素左边部分的元素都比它小,右边部分的元素都比它大,在这个算法的基础上加以修改:
    我们直接将每次选取的元素最终所在位置m与我们想要比较的位置号k相比较。
    若m比k大,说明第k大元素必然在m的左方,此时缩小下一趟排序的上界:high=middle-1;
    反之(k比m大),说明第k大元素必然在m的右方,此时放大下一趟排序的下界:low=middle+1;
    这样就可以在不需要把整个数组元素都排序完的情况下求出第k大的数。

    #include<iostream>
    #include<cstdio>
    #define maxn 10001
    using namespace std;
    int arr[maxn];
    int quicksort(int a[],int low,int high)
    {
        int pivot=a[low];//选取最低位置上的元素作为枢纽元素
        for(;;)
        {
            while(low<high&&pivot<=a[high]) high--;
            if(low>=high)break;
            a[low++]=a[high];
            while(low<high&&a[low]<=pivot)
                low++;
            if(low>=high)break;
            a[high--]=a[low];
        }
        a[high]=pivot;
        return high;//返回最后元素所在位置
    }
    int selectk(int a[],int low,int high,int k)
    {
        int index;
        for(;;)
        {
            index=quicksort(a,low,high);
            if(index==k) return a[k];
            else if(index<k)
                low=index+1;
            else high=index-1;
        }
    }
    int main()
    {
        int n,x,ans;
        while(scanf("%d%d",&n,&x)!=EOF)
        {
            for(int i=0;i<n;i++)
                scanf("%d",&arr[i]);
            ans=selectk(arr,0,n-1,x-1);
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    bzoj 1031: [JSOI2007]字符加密Cipher 後綴數組模板題
    hdu3949 XOR xor高斯消元
    The xor-longest Path
    Contest20140906 反思
    Contest20140906 ProblemC 菲波拉契数制 DP
    Contest20140906 ProblemA dp+线段树优化
    bzoj 1257: [CQOI2007]余数之和sum 数学 && 枚举
    tyvj P1716
    BZOJ 1012 [JSOI2008]最大数maxnumber【线段树】
    Bzoj1083 1083: [SCOI2005]繁忙的都市【MST】
  • 原文地址:https://www.cnblogs.com/AKsnoopy/p/8550072.html
Copyright © 2020-2023  润新知