單峰陣列求第k大演算法

2021-09-09 09:11:49 字數 1400 閱讀 1967

單峰陣列實際上可以看成兩個有序的陣列,這個問題就轉變成了兩個有序陣列求第k大。

容易想到的演算法是對這兩個陣列進行歸併,生成乙個新的有序陣列,求出第k大之後就可以立刻停止,複雜度是o(k)的。

但是還有更優的演算法,可以使用分治的思想(實際上也是一種二分)來計算。

對於兩個有序的陣列a和b,取出他們第k/2個元素進行比較,這種時候就會產生大於、小於和等於三種情況,對於這三種情況:

1、a的取出元素大於b的取出元素

說明b中的前k/2個元素全部小於a的第k/2個元素,第k大一定不在b的前k/2個中,因此這一部分可以全部丟掉,到剩下的部分中去找第k - k/2大。

2、小於的情況,和1剛好相反,丟棄a的前k/2個,去找剩下的k - k/2。

3、相等的情況。

相等的情況比較複雜,如果k是偶數,那麼此刻就已經獲得了第k大(a陣列k/2個,b陣列k/2個,加起來剛好k個),直接返回即可,奇數則需要比較a、b陣列的下乙個數,返回小的那個。

但是這樣討論比較挫,相等的情況實際上可以被包含在上面兩種情況的**裡處理掉,除非空間和時間要求特別大,可以忽略掉。

然後就是某個陣列出現了不足以取k/2個的情況,那麼很顯然,第k大不在這個陣列裡,可以直接減掉這一部分,去另外乙個陣列找。

到了最後,k等於1時,就找到了第k大,返回兩個陣列當前位置的最小值即可。

這樣的演算法用迴圈實現起來真的是難寫,但是用遞迴寫起來就很舒服了,確定好兩個起始位置之後一直往下遞迴就完事了。

**:

#include

using namespace std;

const

int maxn =

1e5+5;

const

int inf =

1e9+7;

int a[maxn]

, b[maxn]

, mid, n;

intkth

(int s1,

int s2,

int k)

if(s2 >= n - mid)

if(k ==1)

int end1 = inf, end2 = inf;

if(s1 + k /2-

1< mid)

if(s2 + k /2-

1< n - mid)

if(end1 < end2)

return

kth(s1, s2 + k /

2, k - k /2)

;}/*8

1 2 4 8 7 3 3 2

*/int

main()

for(

int i =

0; i < n - mid; i++

)while

(cin >> k)

return0;

}

求序列第K大演算法總結

參考部落格 傳送門 在上面的部落格中介紹了求序列第k大的幾種演算法,感覺收益良多,其中最精巧的還是利用快速排序的思想o n 查詢的演算法。仔細學習以後我將其中的幾個實現了一下。解法 1 將亂序陣列從大到小進行排序然後取出前k大,總的時間複雜度為o nlogn 解法 2 利用選擇排序或互動排序,取出前...

求區間第k大

int a mx void insert int a,int l,int r int divide int a,int l,int r 劃分子問題 a l x return l int select int s,int l,int r,int k,int len 返回s陣列l r的第k大數的下標 w...

陣列第K大

和第k小剛好相反 有乙個整數陣列,請你根據快速排序的思路,找出陣列中第k大的數。給定乙個整數陣列a,同時給定它的大小n和要找的k k在1到n之間 請返回第k大的數,保證答案存在。測試樣例 1,3,5,2,2 5,3 返回 2 先排序 快排 二分 第k大,則說明是第n k 1小 目的下標為n k 根據...