資料結構與演算法之美學習筆記 10章 遞迴

2021-10-03 06:23:10 字數 2503 閱讀 5139

週末你帶著女朋友去電影院看電影,女朋友問你,咱們現在坐在第幾排啊?電影院裡面太黑了,看不清,沒法數,現在你怎麼辦?

別忘了你是程式設計師,這個可難不倒你,遞迴就開始排上用場了。於是你就問前面一排的人他是第幾排,你想只要在他的數字上加一,就知道自己在哪一排了。但是,前面的人也看不清啊,所以他也問他前面的人。就這樣一排一排往前問,直到問到第一排的人,說我在第一排,然後再這樣一排一排再把數字傳回來。直到你前面的人告訴你他在哪一排,於是你就知道答案了。

這就是乙個非常標準的遞迴求解問題的分解過程,去的過程叫「遞」,回來的過程叫「歸」。基本上,所有的遞迴問題都可以用遞推公式來表示。剛剛這個生活中的例子,我們用遞推公式將它表示出來就是這樣的:

f(n)=f(n-1)+1 其中,f(1)=1
f(n) 表示你想知道自己在哪一排,f(n-1) 表示前面一排所在的排數,f(1)=1 表示第一排的人知道自己在第一排。有了這個遞推公式,我們就可以很輕鬆地將它改為遞迴**,如下:

int f(int n)
假如這裡有 n 個台階,每次你可以跨 1 個台階或者 2 個台階,請問走這 n 個台階有多少種走法?如果有 7 個台階,你可以 2,2,2,1 這樣子上去,也可以 1,2,1,1,2 這樣子上去,總之走法有很多,那如何用程式設計求得總共有多少種走法呢?

我們仔細想下,實際上,可以根據第一步的走法把所有走法分為兩類,第一類是第一步走了 1 個台階,另一類是第一步走了 2 個台階。所以 n 個台階的走法就等於先走 1 階後,n-1 個台階的走法 加上先走 2 階後,n-2 個台階的走法。用公式表示就是:

f(n) = f(n-1)+f(n-2)
有了遞推公式,遞迴**基本上就完成了一半。我們再來看下終止條件。當有乙個台階時,我們不需要再繼續遞迴,就只有一種走法。所以 f(1)=1。這個遞迴終止條件足夠嗎?我們可以用 n=2,n=3 這樣比較小的數試驗一下。

n=2 時,f(2)=f(1)+f(0)。如果遞迴終止條件只有乙個 f(1)=1,那 f(2) 就無法求解了。所以除了 f(1)=1 這乙個遞迴終止條件外,還要有 f(0)=1,表示走 0 個台階有一種走法,不過這樣子看起來就不符合正常的邏輯思維了。所以,我們可以把 f(2)=2 作為一種終止條件,表示走 2 個台階,有兩種走法,一步走完或者分兩步來走。

所以,遞迴終止條件就是 f(1)=1,f(2)=2。這個時候,你可以再拿 n=3,n=4 來驗證一下,這個終止條件是否足夠並且正確。

我們把遞迴終止條件和剛剛得到的遞推公式放到一起就是這樣的:

f(1) = 1;

f(2) = 2;

f(n) = f(n-1)+f(n-2)

最終**

int f(int n)
1. 乙個問題的解可以分解為幾個子問題的解

何為子問題?子問題就是資料規模更小的問題。比如,前面講的電影院的例子,你要知道,「自己在哪一排」的問題,可以分解為「前一排的人在哪一排」這樣乙個子問題。

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

比如電影院那個例子,你求解「自己在哪一排」的思路,和前面一排人求解「自己在哪一排」的思路,是一模一樣的。

3. 存在遞迴終止條件

把問題分解為子問題,把子問題再分解為子子問題,一層一層分解下去,不能存在無限迴圈,這就需要有終止條件。

還是電影院的例子,第一排的人不需要再繼續詢問任何人,就知道自己在哪一排,也就是 f(1)=1,這就是遞迴的終止條件。

寫遞迴**的關鍵就是找到如何將大問題分解為小問題的規律,並且基於此寫出遞推公式,然後再推敲終止條件,最後將遞推公式和終止條件翻譯成**

編寫遞迴**的關鍵是,只要遇到遞迴,我們就把它抽象成乙個遞推公式,不用想一層層的呼叫關係,不要試圖用人腦去分解遞迴的每個步驟

不過遞迴**也比較難寫、難理解。編寫遞迴**的關鍵就是不要把自己繞進去,正確姿勢是寫出遞推公式,找出終止條件,然後再翻譯成遞迴**。

遞迴**雖然簡潔高效,但是,遞迴**也有很多弊端。比如,堆疊溢位、重複計算、函式呼叫耗時多、空間複雜度高等,所以,在編寫遞迴**的時候,一定要控制好這些***。

1. 現有數字 1,12,123,1234,12345........請問第n個數時多少.(n<9)

遞迴公式 規律

f(n)=f(n-1)*10+n
結束條件

f(1)=1
**

public class test01 

return f(n-1)*10+n;

}public static void main(string args)

}

《資料結構與演算法之美》學習筆記 3 資料結構

陣列定義 陣列 array 是一種線性表資料結構。它用一組連續的記憶體空間,來儲存一組具有相同型別的資料。第一是線性表 linear list 顧名思義,線性表就是資料排成像一條線一樣的結構。每個線性表上的資料最多只有前和後兩個方向。除了陣列,鍊錶 佇列 棧等也是線性表結構。而與它相對立的概念是非線...

《資料結構與演算法之美》學習筆記之開篇

本系列是極客時間中前 google 工程師王爭 資料結構與演算法之美 專欄的學習筆記,想加強資料結構及演算法能力的同學可以直接購買此專欄,跳轉鏈結在此 從廣義上講,資料結構就是指一組資料的儲存結構。演算法就是運算元據的一組方法。資料結構和演算法是相輔相成的。資料結構是為演算法服務的,演算法要作用在特...

資料結構與演算法之美學習筆記 5 9章

陣列是一種線性表資料結構,他用一組連續的記憶體空間,來儲存相同型別的資料 這裡要注意不根據下標是不能隨機訪問的啊 假設乙個長度為10的int型陣列,會分配一塊連續記憶體空間 1000 1039,其中,記憶體塊首位址是1000 我們可以通過以下公式快速獲取到指定下標的元素 a i address ba...