無序數組求第k大/第k小的數


根據http://www.cnblogs.com/zhjp11/archive/2010/02/26/1674227.html

博客中所總結的7種解法,我挑了其中的解法3和解法6進行了實現。

解法3: 利用快速排序的思想,從數組S中隨機找出一個元素X,把數組分為兩部分Sa和Sb。Sa中的元素大於等於X,Sb中元素小於X。這時有兩種情況:
           1. Sa中元素的個數小於k,則Sb中的第k-|Sa|個元素即為第k大數;
           2. Sa中元素的個數大於等於k,則返回Sa中的第k大數。時間復雜度近似為O(n)

 

#include<stdio.h>
#include<string.h>
int par(int a[],int l,int r){
    int x=a[l];
    while(l<r){
        while(l<r&&a[r]<=x)    --r;
        a[l]=a[r];
        while(l<r&&a[l]>=x)    ++l;
        a[r]=a[l];
    }
    a[l]=x;
    return l;
}
int search(int a[],int l,int r,int k){
    if(l<=r){
        int p = par(a,l,r);
        if(p-l+1==k)    return p;
        else if(p-l+1<k){
            return search(a,p+1,r,k-(p-l+1));
        }else{
            return search(a,l,p-1,k);
        }
    }
}
int main(){
    int n,k;
    int a[100];
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    printf("%d\n",a[search(a,1,n,k)]);
    return 0;
}

 

 解法6:維護一個k大小的最小堆,對於數組中的每一個元素判斷與堆頂的大小,若堆頂較大,則不管,否則,彈出堆頂,將當前值插入到堆中。時間復雜度O(n * logk)

注意:這里要求第k大的數,所以要構建的是小頂堆,並且只有當新進來的數大於堆頂也就是目前k個數里最小的數時,才有可能是第k個大的數,才將其加入堆。

 

#include<stdio.h>
#include<string.h> 
#include<iostream>
using namespace std;
void heapAdd(int a[],int i,int num){
    a[i]=num;
    for(int j=i>>1;j&&i&&a[i]<a[j];i=j,j>>=1)
        swap(a[i],a[j]);
}
void heapDown(int a[],int i,int n){
    for(int j=i<<1;j<=n;i=j,j<<=1){
        if(j+1<=n&&a[j+1]<a[j])    j++;
        if(a[i]>a[j])    swap(a[i],a[j]);
    }
}
int a[100],n,k,b[100];
int main(){
    scanf("%d%d",&n,&k);
    int cnt=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        if(cnt<k){
            heapAdd(b,++cnt,a[i]);
        }else{
            if(b[1]<a[i]){
                b[1]=a[i];
                heapDown(b,1,k);
            }
        }
    }
    printf("%d\n",b[1]);
    return 0;
}

 如果要求的是第k小的數,則把相應的判斷條件改一下就可以了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM