參考部落格:傳送門
在上面的部落格中介紹了求序列第k大的幾種演算法,感覺收益良多,其中最精巧的還是利用快速排序的思想o(n)
查詢的演算法。仔細學習以後我將其中的幾個實現了一下。
解法 1:
將亂序陣列從大到小進行排序然後取出前k大,總的時間複雜度為o(nlogn)
解法 2:
利用選擇排序或互動排序,取出前k大,總的時間複雜度為o(nk)
解法 3:
借鑑快速排序的思想,複雜度近似為o(n)
#include
#include
#include
using
namespace std;
intkth_number
(int
*a,int l,
int r,
int k)
}swap
(a[index]
,a[l]);
if(r-index == k)
return a[index];if
(r-index-
1>= k)
return
kth_number
(a,index+
1,r,k)
;else
return
kth_number
(a,l,index,k-r+index)
;}
測試程式
#include
#include
"kth_number.h"
using
namespace std;
intmain()
執行結果
解法 4:
借助堆排序的思想,將前k個數字彈出,複雜度為建立堆的o(4n)
加上k次堆排序o(logn)
為o(4n+klogn)
實現程式
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace std;
void
adjust
(int
*a,int n,
int i)
else
} a[i]
= x;
}void
makeheap
(int
*a,int n)
}void
heapsort
(int
*a,int n,
int k,
int*ans)
*ans = a[m+1]
;}intmain
(int argc,
char
* ar**)
;for
(int i =
1; i <= n;
++i)
int k;
scanf
("%d"
,&k);if
(k > n) k = n;
makeheap
(a, n)
;int ans;
heapsort
(a, n, k,
&ans)
;printf
("ans=%d\n"
, ans)
;return0;
}
測試結果
解法 5:
維護乙個大小為k的小頂堆,對於陣列中的每乙個元素判斷與堆頂的大小,若堆頂較大,則不管,否則彈出堆頂,將當前值插入到堆中。時間複雜度o(4k+nlogk)
實現程式
#include
#include
using
namespace std;
void
adjust
(int
*a,int n,
int i)
else
break;}
a[i]
=x;}
void
makeheap
(int
*a,int n)
}int
kthnumber
(int
*a,int n,
int k)
makeheap
(b,k)
;for
(int i=k+
1;i<=n;
++i)
}return b[1]
;}intmain()
;for
(int i=
1;i<=n;
++i)
scanf
("%d"
,&a[i]);
printf
("%d\n"
,kthnumber
(a,n,k));
// delete a;
return0;
}
測試結果
解法 6:
利用hash
儲存陣列中元素出現的次數,利用計數排序的思想,線性從大到小掃瞄中得到結果,時間複雜度為o(n)
單峰陣列求第k大演算法
單峰陣列實際上可以看成兩個有序的陣列,這個問題就轉變成了兩個有序陣列求第k大。容易想到的演算法是對這兩個陣列進行歸併,生成乙個新的有序陣列,求出第k大之後就可以立刻停止,複雜度是o k 的。但是還有更優的演算法,可以使用分治的思想 實際上也是一種二分 來計算。對於兩個有序的陣列a和b,取出他們第k ...
求區間第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...
演算法題 BFPRT演算法 求第K小或者第K大的數
2017 11 21 bfprt問題 乙個陣列中求第k小或者第k大的數 不通過排序求第k小的數,時間複雜度為o n 1 找到乙個劃分值,按照partition的過程,分為小於區 等於區 大於區,則可知等於區是在整個陣列有序後不變的部分。2 求第k小的數,就是陣列有序後下標為k 1的數。3 所以,如果...