求第k小的數 O n 複雜度

2022-09-02 21:12:19 字數 1150 閱讀 5247

利用快速排序的思想,把陣列遞迴劃分成兩部分。設劃分為x,陣列左邊是小於等於x,右邊大於x。

關鍵在於尋找乙個最優的劃分,經過 blum 、 floyd 、 pratt 、 rivest 、 tarjan五位大牛的研究總結,提出了bfprt 演算法(也就是中位數的中位數演算法)

利用中位數的中位數演算法得到的數作為劃分可以實現最優劃分–在最差情況下能實現o(n)複雜度。接下來考慮可能出現許多重複的數,假設陣列中所有的數全部相同,每次劃分之後都是當前區間的右端點,即會退化到o(n^2)複雜度

乙個比較好的辦法就是改寫partion演算法,設每次劃分的標準數為x,將所有的與x相等的元素集中到一起,例如陣列a=,x=4,劃分之後應該是。很容易能得到等於x的元素的個數cnt,接下來就是決策的處理:

設當前劃分的下標為ind.

如果ind+1==k,直接返回a[ind]

如果ind+1k

可分成兩種情況:

1、k位於重複元素[ind+1-cnt+1,ind+1]之中,直接返回a[ind],直接結束程式.

2、k位於所有重複元素之前,則應該丟棄重複元素,遞迴進入[l,ind-cnt+1)的區間繼續尋找答案

當然,這題n<=10^6,直接用sort以o(nlgn)也能過。

#include

#include

using

namespace

std;

const

int maxn=1e6+5;

int a[maxn];

int n,k;

inline

int findmid(int l,int r)

return findmid(l,l+(r-l)/5);

}int partion(int l,int r,int &p)

++p;

swap(a[++ind],a[r-1]);

int i=l,j=ind-1;

while(iif(a[i]==a[ind])

int solve(int l,int r)

if(ind+1

return solve(ind+1,r);

}int main()

找第k大數,最壞時間複雜度O n

以前寫過的一篇,搬過來。上演算法課的時候聽到老師講這個問題,覺得還是蠻有意思的。已知陣列a,找出a m a p 中的第k大值。很容易想到快排和冒泡。第一種方法 用快排的分治方法,是先任意找陣列中的乙個元素a a用陣列的第乙個元素比較方便 然後進行一次劃分,就是將陣列中所有大於a的數都移到a的一邊,所...

找第k大數,最壞時間複雜度O n

第一種方法 用快排的分治方法,是先任意找陣列中的乙個元素a a用陣列的第乙個元素比較方便 然後進行一次劃分,就是將陣列中所有大於a的數都移到a的一邊,所有小於等於a的數都移到a的另一邊。然後選擇在哪邊繼續進行劃分,最後找到第k大的值。第二種方法 用冒泡的方法,是每個元素挨著比,第一趟找出最大的數,第...

最大k乘積的時間複雜度 時間複雜度 空間複雜度

為了讓廣大讀者輕鬆學習,完全理解內容表達含義。我會用最通俗易通的方式結合 表達,讓每位讀者完全熟記每種資料結構和演算法的優缺點!今天我們分享的是時間複雜度和空間複雜度,因為只要講到資料結構與演算法,就一定離不開時間 空間複雜度分析。首先,什麼是時間複雜度?簡單的講就是指執行這個演算法所需要的執行時間...