面對這個問題,最簡單的想法是對資料進行排序,然後根據下標即可找到第k小的元素,目前已知的排序演算法的最低時間複雜度為o(n
log
2log2
n)
o(n\sqrt})
o(nlog2
log2n
),但並不為人熟知。目前應用最廣的排序演算法的最低時間複雜度為o(n
log2n
)o(n\log_2 n)
o(nlog2
n)。但是,作為完美主義者的程式設計師,需要思考,找到第k小的元素一定需要排序嗎?但除了尋找最大或最小的元素之外,我們似乎只能選擇排序。那麼能否只進行部分排序,便可找到第k小的元素呢?答案是顯然的,只需要採用每一趟都能確定乙個固定元素的排序演算法即可。
思考o (n
log2n
)o(n\log_2 n)
o(nlog2
n)的排序演算法中有哪些演算法每一趟可以確定乙個固定元素,答案是快速排序和堆排序(不考慮錦標賽排序,堆排序是錦標賽排序的公升級版)。這裡以快速排序為例,方便引入後面介紹的bfprt演算法,不過還有乙個原因是堆排序獲取第k小的元素的時間複雜度是o(n
)o(n)
o(n)
的概率小於快速排序。
我們知道,快排每一趟都會有隨機有乙個元素處於最終位置上,故只需在快排中設定乙個新的遞迴出口再加以微改便能返回第k小的元素。
**如下:
這裡採用的快排為隨機化快速排序,沒有了解過的的朋友可以看一下我的另外一篇部落格:公升級版快速排序——隨機化快速排序
templatevoid partition(t array,int left,int right,int& mid)
array[i] = temp;
mid = i;
}templatet random_quick_sort(t array, int left, int right,int k)
這個演算法的時間複雜度的確定需要用到指示器隨機變數。e[t
(n)]
=e[∑
k=0n
−1xk
(t(m
ax
e[t(n)]=e[\sum_^x_k(t(max
e[t(n)
]=e[
∑k=0
n−1
xk(
t(max))
+θ(n
)]
))+\theta(n)]
))+θ(n
)],最終得到e[t
(n)]
=θ(n
)e[t(n)]=\theta(n)
e[t(n)
]=θ(
n),即該演算法的時間複雜度的期望值為o(n
)o(n)
o(n)
但是存在最壞情況,即每一次劃分只能劃分出乙個部分,即t(n
)=t(
n−1)
+θ(n
)t(n)=t(n-1)+\theta(n)
t(n)=t
(n−1
)+θ(
n),由等差級數可以得到最壞情況下的時間複雜度為o(n
2)
o(n^2)
o(n2
)不想寫了,困了
重寫了這篇部落格,新內容已放進去,轉到那邊去吧:找到第k小的元素【top-k】:快排應用與bfprt演算法
選擇問題 線性時間內找到序列的第k小的元素
選擇問題 在序列中按順序找到某個元素。這可以用排序方法做到,即先排個序,在找到指定元素,但是這樣就按最快的堆排序 合併排序啥的都得是o nlgn 數量級的,這裡採取的方法可以在期望為o n 的時間內完成。具體的實現方式如下 int select int a,int begin,int end,int...
快排擴充套件 第k小的數
使用快排中的partition方法,可以很快找到乙個無序序列中的第k小的數。思想 對於乙個陣列a 0.n 1 分段成a 0.st 1 a s a st 1.n 1 分組後,a 0.st 1 裡面的元素都小於等於a st a st 1.n 1 裡面的元素都大於等於a st 所以,如果 st k 1,那...
選擇第K大元素(快排 快選以及k 選取比較)
先看執行結果 按照書中所給的快排 快選以及k 選取演算法分別寫出函式檢測執行結果以及時間 發現不出所料的直接快排演算法會慢很多,但預想更穩定的k 選取演算法的耗時比預期設想要大,而相對不太穩定的快選演算法卻是三者之中最快的,為了避免偶然性,又重複做了多組實驗,並將n的範圍擴大到100 1000000...