概述:在設計算法的時候,要考慮兩個方面,一個是算法的正確性,另外一個就是算法的效率,也就是復雜度,通常情況下,我們優先考慮的是時間復雜度,這也是本文要討論的內容。算法學習的時候,經常碰到這樣的問題,為什么快速排序的時間復雜度是O(nlog(n))?為何插入排序的時間復雜度是O(n^2)?這些是我們熟悉的算法時間復雜度,可能病沒有太大的問題,那我們不熟悉的呢?如果我們采用三路歸並排序而不是二路歸並排序,時間復雜度是多少呢?一個排序算法經過某種變形以后時間復雜度又是多少呢?本文,主要從數學底層,講述一個算法時間復雜度是如何推導的。讓你真正知其所以然,而不僅僅是總是心中存有疑惑:為何快排的時間復雜度會是這么奇怪的O(nlog(n))
1.數學基礎知識
首先,介紹以下數學基礎知識,這些基本都分布在高等數學和離散數學之中,不進行數學推導。
一些不等式:
無論是歸並還是快速排序,我們都可以把它們歸結到遞歸/分治這一類問題的求解,他們具有一個一般性的時間復雜度表述:
這個等式的意義是:規模是n的問題可以拆分成a個規模是n/b的問題,那么它的時間復雜度就等於a個規模是n/b的問題,加上一次分解耗費的時間D(n)和一次合並耗費的時間C(n)。第二部分到第四部分將介紹三種求解這個方程式的方法。
2.遞歸樹方法
這是一種最直觀的方法,它把上述等式形象化,然后進行求解,我們通過一個例子來說明這個情況。
例子:利用遞歸樹求解T(n)=T(n/10)+T(9n/10)+cn
划出遞歸樹如下:
關鍵點:求出樹的深度和每層的代價(注意,此例中因為每層的代價都相同,所以比較好求解;但在其他情況下,可能是每層代價不同,而是一個等比數列或者其他形式的數列)
1)其中,樹的深度容易求解:n-->9/10n-->81/100(n)......n/n=1
也就是說,這個遞歸下降滿足這個趨勢(其中b=10/9):
於是
所以
2)第i層的代價:
每層的規模分別是1/10n和9/10n,而每個節點的代價是cn/10和9cn/10,所以加在一塊是cn。
3)總代價:
所以
T(n)=O(nlgn)
3.主方法
形如下列表達式的算法復雜度表述
T(n)=aT(n/b)+f(n)(a>=1,b>1)
主方法的證明:參考算法導論第四章
最終利用等比數列的求和公式即可求解。
4.替換代換法
說明:此種方法需要憑借一定的經驗,有點類似於數學歸納法,先猜測后證明。
1)步驟:猜測時間復雜度的表述形似
2)要點:猜測要准確,歸納假設要足夠強,避免弱化證明。替換非多項式變量
對於邊界問題:可采用移動邊界和強化歸納假設的方式加以解決。
實例:
1)證明T(n)=T(n/2)+n的時間復雜度位O(nlogn)
令T(n)<cnlgn
則
說明:此種算法復雜度的計算對以分支法為基礎的算法比較有效。