一、引言
今天學了乙個快速選擇演算法,這個演算法跟快排差不多,只不過專門用來在選擇陣列中第k大/小的數時,可以免去將整個陣列排序後選擇第k個數。將整個陣列排序再選擇第k個數的時間複雜度是o(nlog(n)),快速選擇演算法將平均時間複雜度優化到o(n),但最壞的情況還是o(n^2)。一開始很糾結這個o(n)是怎麼來的,後來看了一下別人的分析,得到了答案。
二、分析
這裡大概分析一下o(n)怎麼來的,可能不是很嚴謹。
(1)快速選擇演算法,每次根據pivot(樞紐值)將陣列分成左部分和右部分以後,根據k值的大小選擇下一次進入左部分還是右部分,我們把陣列分成左右部分的過程叫partition。
(2)假設用隨機選擇演算法取得的樞紐值總是在陣列的中間,那每次都會將陣列分成等長(或長度相差1)的兩半,再假設如果一直到最後子陣列長度為1才找到第k大/小的值,那就一共要進行⌊logn⌋+1次partition。
(3)第一次partition要遍歷的長度是n,第二次要遍歷的長度是n/2,第三次要遍歷的長度是n/4……倒數第二次遍歷的長度是2,最後一次遍歷的長度是1。這是乙個首項為1,公比為2的等比數列,記ax=2^(x-1),其中x為項數。這個等比數列的前x項和為2^x-1(等比數列的求和公式為sx=(a1-ax*q)/(1-q))。因為一共要求⌊logn⌋+1次partition,而s(⌊logn⌋+1)=2^(⌊logn⌋+1)-1≈2n-1(大概是這樣,會有誤差,但主要是看數量級。數學這方便確實比較菜嘻嘻),所以時間複雜度是o(2n-1)=o(n)。
三、總結
一開始覺得快速選擇演算法的平均時間複雜度應該跟快排一樣是o(nlogn),因為覺得要進行⌊logn⌋+1次的partition,每次最差都要遍歷長度為n的陣列(被以前那些o(n^2)分析帶偏了)。實際上每次partition平均來說只要遍歷n/2的長度。時間複雜度分析不能想當然,還是要用數學的方式推導一下。
演算法時間複雜度空間複雜度
演算法 是解決某一類問題的通法,即一系列清晰無歧義的計算指令。每個演算法只能解決具有特定特徵的一類問題,但乙個問題可由多個演算法解決。乙個演算法應該有以下五個方面的特性 比較演算法的優劣我們從兩個維度去進行考量 時間 空間 時間複雜度,空間複雜度 找出基本語句 演算法中執行次數最多的那條語句就是基本...
演算法 時間複雜度 空間複雜度
1 if i 1 2 a 1 result 3 4 result n 2 result 1000 1000 3 array.push a array.pop 4 map.set 1,1 map.get 1,1 在計算複雜度的時候,o 1 一般會被忽略。1 for let i 0 i n i 2 wh...
演算法的時間複雜度 空間複雜度
時間複雜度和空間複雜度是度量演算法效率的常用指標 事後統計,不常用 事前統計影響因素 演算法策略 問題規模 程式語言 質量 機器執行指令的速度 撇開軟硬體的影響,演算法執行工作量的大小只依賴於問題的規模 通常用整數n表示 乙個演算法是由控制結構 順序,分支,迴圈三種 和原操作 指固有資料型別的操作 ...