利用快速排序的思想,把陣列遞迴劃分成兩部分。設劃分為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乘積的時間複雜度 時間複雜度 空間複雜度
為了讓廣大讀者輕鬆學習,完全理解內容表達含義。我會用最通俗易通的方式結合 表達,讓每位讀者完全熟記每種資料結構和演算法的優缺點!今天我們分享的是時間複雜度和空間複雜度,因為只要講到資料結構與演算法,就一定離不開時間 空間複雜度分析。首先,什麼是時間複雜度?簡單的講就是指執行這個演算法所需要的執行時間...