遞迴演算法的時間複雜度分析
在演算法分析中,當一個演算法中包含遞迴調用時,其時間複雜度的分析會轉化為一個遞迴方程求解。實際上,這個問題是數學上求解漸近階的問題,而遞迴方程的形式多種多樣,其求解方法也是不一而足,比較常用的有以下四種方法:
方法一:代換法
代換法主要需要以下兩個步驟
1、 猜答案,不需要完全猜出來,不需要知道常熟係數的準確值,而只需要猜出它的形式,比如猜一個遞迴式的時間複雜度大概是O(n2),即它的已耗用時間應該是一個常熟乘以n2,可能還會有一些低階項。
方法二:遞迴樹法
遞迴樹法主要是通過遞迴樹將遞迴式展開來找到答案,然後再用代換法證明它,因為遞迴樹法是不嚴謹的。
例如,用遞迴樹法求T(n) = T(n/2) + n2 , 用遞迴樹法將該遞迴式展開
像這樣將遞迴樹展開並延伸下去,最終到葉子節點就只剩下T(1),那麼該遞迴樹的高度就是logn,因為從頂點n出發,到n/2,到n/4,……最後到1,那麼從n到1的折半次數是logn,即高度是logn(應該是一個常數乘以logn,不過沒多大關係)。而最下面葉子節點的數目是n,因為從第一層往下,節點數變化為1,2,4,8……,如果樹的高度是h,那麼就會有2h個分葉節點,而高度是logn,那麼2logn=n。那麼,整體所做的工作加起來就是T(n)了
T(n) = [1+1/2+1/4+……]n2 = 2n2,於是可知時間複雜度為T(n) = O(n2)。
再例如,用遞迴樹法求T(n) = T(n/4)+T(n/2)+n2 ,下面用遞迴樹的方法將該遞迴式展開
最後,求葉子節點的數目有點麻煩,因為分支的遞迴速度是不一樣的,左邊降低到n/16的時候,右邊才降低到n/4,左邊子樹的高度將會比右邊子樹的高度要小。可以看到葉子節點的數目必然小於n,因為最開始的問題大小是n,然後遞迴成一個n/4和n/2的兩個子問題,直到最後遞迴到1停止,而n/4+n/2 < n , 所以最後葉子節點的數目不會超過n,將每層求和就得到T(n),經過觀察發現一個等比數列,於是數學歸納法開始派上用場
T(n) = (1+5/16+25/256+……)n2≤2n2 =O(n2) 於是得到該遞迴式時間複雜度為O(n2),因為是猜出來的等比數列,於是需要用數學歸納法證明之,就又變成方法一中代換法求證了。
方法三:主方法 (master method)
該方法僅適用於特定格式的遞迴式
同時要求f(n)漸進趨正,即當n->無窮時,f(n)>0。(我覺得中第2,3中少了個logn,具體請參考演算法導論一書中對時間複雜度的討論)
例如:
T(n)=4T(n/2)+n , 則a=4,b=2,f(n)=n,計算nlog(b,a)=n2>f(n), 滿足模式一,因此T(n) = nlog(b,a)=O(n2)
T(n)=4T(n/2)+n2,則根據上面計算,滿足模式二,因此T(n)=O(n2logn)
T(n)=4T(n/2)+n3,滿足模式三,T(n)=O(n3)
對於該方法的正確性,可以通過遞迴樹的方法證明,懶的畫了,可以在大腦裡構思出這樣一個草圖:
在第一層,f(n)分解為a個子問題,每個子問題都是f(n/b),第二層每個子問題又分解為a個子問題,每個問題都是f(n/b2)……這樣遞迴分解下去,最後的葉子還是O(1),整個樹的高度就是log以b為底n的對數,整個的葉子節點數目為a的log以b為底n的對數次方(alog(b,n)),即nlog(b,a)個葉子節點。每個分支的遞減速度是一樣的,將每層都加在一起便得到T(n)
,此時就需要對f(n)的情況進行討論(於是就是上面的1,2,3)。