資料結構 遞迴

2021-09-29 01:16:59 字數 1754 閱讀 3305

最近開始學習王爭老師的《資料結構與演算法之美》,通過總結再加上自己的思考的形式記錄這門課程,文章主要作為學習歷程的記錄。

遞迴是一種非常高效、簡潔的編碼技巧,一種應用非常廣泛的演算法,比如dfs深度優先搜尋、前中後序二叉樹遍歷等都是使用遞迴。基本上所有的遞迴問題都可以用遞推公式來表示。以尋找電影排數為例,只需要問前一排人的排數,然後前一排的人再向前詢問······用遞推公式表示即為f(n)=f(n-1)+1,f(1)=1,將其改為遞迴**,如下:

int f(int n)
遇到什麼樣的問題時可以運用遞迴呢?有三個條件需要滿足:

1.乙個問題的解可以分解為幾個子問題的解,即將問題分解為資料規模更小的問題。

2.這個問題與分解之後的子問題,除了資料規模不同,解題思路完全一樣。

3.存在遞迴終止條件

以leetcode第70題爬樓梯為例,假設你正在爬樓梯。需要 n 階你才能到達樓頂。每次你可以爬 1 或 2 個台階。你有多少種不同的方法可以爬到樓頂呢?

實際上,可以根據第一步的走法將所有走法分為兩類,第一類是第一步走了乙個台階,另一類是第一步走了兩個台階,用公式表示就是f(n)=f(n-1)+f(n-2),終止條件為f(1)=1,f(2)=2,此時,將其轉化為**為:

int f(int n)
寫遞迴**的關鍵就是找到如何將大問題分解為小問題的規律,並且基於此寫遞推公式,然後再推敲終止條件,最後將遞推公式和終止條件翻譯成**。對於遞迴**,若試圖想清楚整個遞和歸的過程,實際上是進入了乙個思維誤區。

那該如何理解遞迴**呢?如果乙個問題a可以分解為若干個子問題b、c、d,你可以假設子問題b、c、d已經解決。而且,你只需要思考問題a與子問題b、c、d兩層之間的關係即可,不需要一層層往下思考子問題與子子問題,子子問題與子子子問題之間的關係。遮蔽掉遞迴細節,這樣子理解起來就簡單多了。

因此,理解遞迴**,就把它抽象成乙個遞推公式,不用想一層層的呼叫關係,不要試圖用人腦去分解遞迴的每個步驟。

1.警惕堆疊溢位:遞迴呼叫超過一定深度(比如1000之後),就不再繼續往下遞迴,直接返回報錯,宣告乙個全域性變數來控制遞迴的深度,從而避免堆疊溢位。

2.警惕重複計算:通過某種資料結構來儲存已經求解過的值,從而避免重複計算。

除了堆疊溢位和重複計算這兩個問題,遞迴**還存在很大問題:在時間效率上,遞迴**中多了很多函式呼叫,當數量較大時,就會積聚成乙個可觀的時間成本。在空間複雜度上,因為遞迴呼叫一次就會在記憶體棧中儲存一次現場資料,所以在分析遞迴**空間複雜度時,需要額外考慮這部分的開銷。

遞迴有利有弊,利是遞迴**的表達力很強,寫起來非常簡潔;而弊就是存在許多問題,如空間複雜度高、有堆疊溢位的風險、存在重複計算、過多的函式呼叫會耗時較多等問題。所以,在開發過程中,我們要根據實際情況來選擇是否需要用遞迴的方式來實現。

我們可以將遞迴**轉為非遞迴**,以爬樓梯為例:

class solution(object):

def climbstairs(self, n):

""":type n: int

:rtype: int

"""if n == 1:

return 1

elif n == 2:

return 2

elif n>2:

a,b = 1,2

for i in range(2,n):

a,b = b,a+b

return b

當n大於2時,f(n)=f(n-1)+f(n-2),此時就轉化為斐波那契數列,通過a,b = b,a+b即可進行迭代。

資料 結構 遞迴

遞迴不一定非要像斐波拉契數列一樣在return中呼叫函式 遞迴的結束條件就是初始條件值 通常的方法將遞迴呼叫放在if語句中 n!通過遞迴實現 常用方法還是通過while實現 def jiecheng n if n 0 return 1 else sum n jiecheng n 1 右邊只有階乘表示...

資料結構 遞迴

所謂遞迴,就是在乙個函式,過程,或者資料結構的內部,又直接或間接出現定義本身的應用。在以下三種情況中,常常使用遞迴。比如階乘函式,我們能夠將其分解成幾個小問題來求解,比如求5!我們可以先求4!想求4!先求3!這樣一步步使問題簡化的方法,稱之為分治法。採取分治法求解,需要滿足下面三個條件 1.能夠將乙...

資料結構 遞迴

1.明確這個函式想要幹什麼 例如,我定義了乙個函式,想要算n的階乘 算 n 的階乘 假設n不為0 def f n return none第二要素 尋找遞迴結束條件 所謂遞迴,就是會在函式內部 中,呼叫這個函式本身,所以,我們必須要找出遞迴的結束條件,不然的話,會一直呼叫自己,進入無底洞。也就是說,我...