遞歸式的時間複雜度通常都不太好理解,求證,算法導論裏給出了三種求解遞歸式時間複雜度的方法:html
一、代換法 (憑直覺,經驗)git
實際使用的是概括法,即根據直覺經驗判斷結果應該是什麼,而後再概括求解。github
先帶入常量c,而後概括得出這樣的c存在算法
Ex1: T(n) = T(n-1) + n, 咱們先猜想解是O(n^2) 假定對於任意的m<n, T(m) <= cm^2,帶入遞歸式 T(n) <= c(n-1)^2 + n = cn^2 - 2cn + c + n = cn^2 - ((2c-1)n - c) <= cn^2 可見只要c>1,n>0,而n本就要求大於0,故((2c-1)n - c)>0,故T(n)<=O(n^2),得證 Ex2:T(n) = 2T(n/2)+n, 咱們先猜想解是O(nlgn) 假定對於任意的m<n, T(m)<=cmlgm, 帶入遞歸式可得 T(n) <= 2c(n/2)lg(n/2)+n = cnlg(n/2)+n <= cnlgn-cnlg2+n = cnlgn-(c-1)n 可見只要c>1,(c-1)n > 0, 故T(n)<=cnlgn,因此咱們的猜想是正確的,因此得證
但這不是首選的方法,由於猜想的形式很難,須要積累不少的求解的經驗函數
二、遞歸樹法工具
遞歸樹法不是那麼精確,取決於你畫遞歸樹的精確度。用遞歸樹來猜想上界,而後用上面的代換法來證實正確性post
Ex1: T(n) = T(n-1) + O(n) T(1) = 1 n n / T(n-1) n-1 / T(n-2) n-2 ... . / . T(1) 1 樹高度n,1+2+...+n=n(n-1)/2,即O(n^2) Ex2:T(n) = 2T(n/2)+O(n) T(1) = 1 n n / \ T(n/2) T(n/2) n/2+n/2=n / \ / \ T(n/4) T(n/4) T(n/4) T(n/4) n/4+...=n ... / \ n/8+...=n T(1) T(1) 1+1+...=n 樹高度log2^n,即log2^n個n即nlog2^n,即O(nlog2^n) Ex3:T(n) = 3T(n/2)+O(n) T(1) = 1, 3T(n/2)下級分3個 n n | | | T(n/2) T(n/2) T(n/2) (3/2)n | | | | | | ... T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) (3/2)^2 n ... / T(1) 由於2倍數遞減,因此樹高度log2^n,(1+3/2+(3/2)^2+(3/2)^3...)*n=(1 + (3/2)(1-(3/2)^log2^n)/(1-(3/2)))*n,即O(nlog2^3)即O(n^1.585) 注:等比數列前n項和公式爲:Sn=首項*(1-公比的n次方)/(1-公比)
3. 主方法(首推).net
主方法使用的狀況是遞歸式知足T(n)=aT(n/b)+f(n)T(n)=aT(n/b)+f(n),在這種狀況下主方法假設子問題具備相同的大小,主方法是一個用來解遞歸式漸進時間複雜度的黑盒工具。code
下面是簡潔描述版本htm
- a:子問題數量
- b:子問題大小的所見係數
- d:遞歸過程以外的運行時間對問題規模n的指數係數
- a, b, d獨立於n
Case1中的log函數沒寫base,由於這裏得base對時間複雜度的影響僅僅在常係數下,而Case3中的log函數在指數上,因此不能忽略
Ex:
T(n)=3T(n/4)+n2: a=3 b=4 d=2, 3<16,a<b^d, case2, 得O(n^d)=O(n^2) T(n)=2T(n/4)+√n a=2 b=4 d=1/2, 2=2, a=b^d, case1, 得O(n^dlogn)=O(n½logn) T(n)=4T(n/4)+√n a=4 b=4 d=1/2, 4>2, a>b^d, case3, 得O(n^logb^a)=O(n) T(n)=2T(n/2)+nlgn 由表達式得知,n^logb^a=n^log2^2, 因爲 f(n)/n^logb^a=nlgn/n=lgn, 對於 任意的 ω, 都不存在 lgn>n^ω, 故此不可被主方法求解。
引例:
http://raytaylorlin.com/Tech/algorithm/master-method/
http://blog.csdn.net/weixin_36497128/article/details/52914255
http://haiyangxu.github.io/posts/2014/2014-05-03-mastermethod.html