設計一組N個數,確定其中第k個最大值

今天看算法分析是,看到一個這樣的問題,就是在一堆數據中查找到第k個大的值。

      名稱是:設計一組N個數,確定其中第k個最大值,這是一個選擇問題,當然,解決這個問題的方法很多,本人在網上搜索了一番,查找到以下的方式,決定很好,推薦給大家。

      所謂“第(前)k大數問題”指的是在長度爲n(n>=k)的亂序數組中S找出從大到小順序的第(前)k個數的問題。

      解法1: 我們可以對這個亂序數組按照從大到小先行排序,然後取出前k大,總的時間複雜度爲O(n*logn + k)。
      解法2: 利用選擇排序或交互排序,K次選擇後即可得到第k大的數。總的時間複雜度爲O(n*k)
      解法3: 利用快速排序的思想,從數組S中隨機找出一個元素X,把數組分爲兩部分Sa和Sb。Sa中的元素大於等於X,Sb中元素小於X。這時有兩種情況:
           1. Sa中元素的個數小於k,則Sb中的第k-|Sa|個元素即爲第k大數;
           2. Sa中元素的個數大於等於k,則返回Sa中的第k大數。時間複雜度近似爲O(n)
      解法4: 二分[Smin,Smax]查找結果X,統計X在數組中出現,且整個數組中比X大的數目爲k-1的數即爲第k大數。時間複雜度平均情況爲O(n*logn)
      解法5:用O(4*n)的方法對原數組建最大堆,然後pop出k次即可。時間複雜度爲O(4*n + k*logn)
      解法6:維護一個k大小的最小堆,對於數組中的每一個元素判斷與堆頂的大小,若堆頂較大,則不管,否則,彈出堆頂,將當前值插入到堆中。時間複雜度O(n * logk)
      解法7:利用hash保存數組中元素Si出現的次數,利用計數排序的思想,線性從大到小掃描過程中,前面有k-1個數則爲第k大數,平均情況下時間複雜度O(n)

這裏實現的是解法3
#include<iostream>
#include<stdio.h>
using namespace std;

int Partition (int *L, int low, int high)
{
int temp = L[low];
int pt   = L[low]; //哨兵
while (low != high)
{
while (low < high && L[high] >= pt)
high--;
L[low] = L[high];

while (low < high && L[low] <= pt)
low++;
L[high] = L[low];
}

L[low] = temp;
return low;
}

void QSort (int *L, int low, int high)  //快速排序
{
int pl;
if (low < high)
{
pl = Partition (L,low,high);
QSort (L, low,  pl-1);
QSort (L, pl+1, high);
}
}
void findk(int k,int *L,int low,int high)
{
int temp;
temp=Partition(L,low,high);
if(temp==k-1)
{
cout<<"第"<<temp+1<<"大的數是:"<<L[temp]<<endl;
}
else if(temp>k-1)
findk(k,L,low,temp-1);
else
findk(k,L,temp+1,high);

}

int main()
{
int a[10]={15,25,9,48,36,100,58,99,126,5},i,j,k;
cout<<"排序前:"<<endl;
for(i=0;i<10;i++){
cout<<a[i]<<" ";
}
cout<<endl;
cout<<"請輸入你要查找第k大的數:"<<endl;
cin>>k;
findk(k,a,0,9);
QSort(a,0,9);

cout<<"排序後:"<<endl;
for(i=0;i<10;i++){
cout<<a[i]<<" ";
}
cout<<endl;
system("Pause");
return 0;

}
發佈了87 篇原創文章 · 獲贊 28 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章