第k小演算法
我們通常會簡單地進行乙個快速排序後,得到第k個位置上的數字即可。
我們都知道的是快速排序是個不穩定的排序,它的排序過程簡單的理解主要是兩個概念partion,pivot(基準數)
一趟快速排序的過程如下
先從序列中選取乙個數作為基準數
將比這個數大的數全部放到它的右邊,把小於或者等於它的數全部放到它的左邊
一趟快速排序也叫做partion,即將序列劃分為兩部分,一部分比基準數小,另一部分比基準數大,然後
再進行分治過程,因為每一次partion不一定都能保證劃分得很均勻,所以最壞情況下的時間複雜度不能
保證總是o(nlogn)的。
bfprt演算法
在bfptr演算法中,僅僅是改變了快速排序partion中的pivot值的選取,在快速排序中,我們始終選擇第乙個元
素或者最後乙個元素作為pivot,而在bfptr演算法中,每次選擇五分中位數的中位數作為pivot,這樣做的目的
就是使得劃分比較合理,從而避免了最壞情況的發生。演算法步驟如下
(1)將輸入陣列的n個元素劃分為n/5組,每組5個元素,且至多只有乙個組由剩下的n%5個元素組成。
(2)尋找n/5個組中每乙個組的中位數,首先對每組的元素進行插入排序,然後從排序過的序列中選出中位數。
(3)對於(2)中找出的n/5個中位數,遞迴進行步驟(1)和(2),直到只剩下乙個數即為這n/5個元素的中位數,找到中位數後並找到對應的下標p。
(4)進行partion劃分過程,partion劃分中的pivot元素下標為p。
(5)進行高低區判斷即可。
本演算法的最壞時間複雜度為o(n),值得注意的是通過bfptr演算法將陣列按第k小(大)的元素劃分為兩部分,而
這高低兩部分不一定是有序的,通常我們也不需要求出順序,而只需要求出前k大的或者前k小的。
#include #include#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define ll long long
#define maxn 1000010
using
namespace
std;
const
int n = 1000005
;int
a[n];
int findmedian(int a , int l , int
r)
if(i<=r)
if(index == 1) return
a[l];
else
return findmedian(a , l , l+index-1);}
//以p位置上的數字作為基準點劃分,返回的i是最後基準點所在的位置
int partion(int a , int l , int r , int
p) a[i] =pivot;
returni;}
//在a陣列的[l,r]區間內找到第k小的數字,k從1開始
int findkthmin(int a , int l , int r , int
k)int
main()
return0;
}
其實bfprt的partion部分和快排的patition方法是差不多的。只是基準點的選取不一樣罷了
演算法題 BFPRT演算法 求第K小或者第K大的數
2017 11 21 bfprt問題 乙個陣列中求第k小或者第k大的數 不通過排序求第k小的數,時間複雜度為o n 1 找到乙個劃分值,按照partition的過程,分為小於區 等於區 大於區,則可知等於區是在整個陣列有序後不變的部分。2 求第k小的數,就是陣列有序後下標為k 1的數。3 所以,如果...
第k個小的數 bfprt演算法與快排改進
public static intfindk int nums,int m,int n int k while i temp if i nums m nums j nums j temp if j 1 k else if j 1 k else public static void main stri...
分治演算法求第k小元素
1.問題 用分治的演算法求乙個陣列s n 中第k小的元素。2.解析 採取和快速演算法相同的思路,但是結合分治的思想,選取恰當的基準值。找到基準值以後,再按照快速排序的方法進行查詢就好了。3.設計 int r 5int r group ceil high low 1 1.0 r ceil取上限,總共分...