遞迴-Recurison
一、什麼是遞迴?
- 遞迴是一種非常高效、簡潔的編碼技巧,一種應用非常廣泛的演算法,比如DFS深度優先搜尋、前中後序二叉樹遍歷等都是使用遞迴。
- 方法或函式呼叫自身的方式稱為遞迴呼叫,呼叫稱為遞,返回稱為歸。
-
基本上,所有的遞迴問題都可以用遞推公式來表示,比如
f(n) = f(n-1) + 1;
f(n) = f(n-1) + f(n-2);
f(n)=n*f(n-1);
二、為什麼使用遞迴?遞迴的優缺點?
- 優點:程式碼的表達力很強,寫起來簡潔。
- 缺點:空間複雜度高、有堆疊溢位風險、存在重複計算、過多的函式呼叫會耗時較多等問題。(函式呼叫會使用棧來儲存臨時變數。每呼叫一個函式,都會將臨時變時變數封裝為棧幀壓入記憶體棧,等函式執行完成返回時,才出棧。系統棧或者虛擬機器棧空間一般都不大。如果遞迴求解的資料規模很大。如果遞迴求解的資料規模很大,呼叫層次很深,一直壓入棧,就會有堆疊溢位的風險。 )
三、什麼樣的問題可以用遞迴解決呢?
一個問題只要同時滿足以下3個條件,就可以用遞迴來解決:
- 問題的解可以分解為幾個子問題的解。何為子問題?就是資料規模更小的問題。
- 問題與子問題,除了資料規模不同,求解思路完全一樣
- 存在遞迴終止條件
四、如何實現遞迴?
-
遞迴程式碼編寫
寫遞迴程式碼的關鍵就是找到如何將大問題分解為小問題的規律,並且基於此寫出遞推公式,然後再推敲終止條件,最後將遞推公式和終止條件翻譯成程式碼。 -
遞迴程式碼理解
對於遞迴程式碼,若試圖想清楚整個遞和歸的過程,實際上是進入了一個思維誤區。
那該如何理解遞迴程式碼呢?如果一個問題A可以分解為若干個子問題B、C、D,你可以假設子問題B、C、D已經解決。而且,你只需要思考問題A與子問題B、C、D兩層之間的關係即可,不需要一層層往下思考子問題與子子問題,子子問題與子子子問題之間的關係。遮蔽掉遞迴細節,這樣子理解起來就簡單多了。
因此,理解遞迴程式碼,就把它抽象成一個遞推公式,不用想一層層的呼叫關係,不要試圖用人腦去分解遞迴的每個步驟。
五、遞迴常見問題及解決方案
- 警惕堆疊溢位:可以宣告一個全域性變數來控制遞迴的深度,從而避免堆疊溢位。
- 警惕重複計算:通過某種資料結構來儲存已經求解過的值,從而避免重複計算。