例題: 計算給定的n個數的和分析: 顯然當n=0的a[0]為所求,因此可以將前n項可以看做是前n-1 即(a[0,n - 2])項的和加上第n項
int
sum(
int a,
int n)
如上演算法中的sum( )在進行遞迴呼叫的時對自身的呼叫最多隻會進行一次,也就是在每一層次上至多只有乙個例項,且構成乙個線性結構,因此稱為線性遞迴 (linear recursing)
線性遞迴往往對應所謂減而治之(decrease-and-conquer)
即在遞迴每深入一層,待求解的問題就縮小乙個常數級別,知道最終蛻化為乙個簡單問題
分而治之: 將乙個規模龐大的問題分解為若干規模更小的子問題,再通過遞迴機制,將子問題繼續分解,知道子問題分解為平凡情況,這種方法就是分而治之(divide-and-conquer)
和減而治之一樣,在這裡需要保證每乙個子問題需要和原問題在形式上保持一致,而在遞迴的每層中都可能做多次遞迴操作,所以也稱為多路遞迴(multi-way recursion)
,又因為通常採用將問題一分為二,所以也稱為二分遞迴(binary recursion)
將上述例題以二分遞迴的模式進行分析:分析: 以居中元素為界限,將陣列一分為二,遞迴對子陣列求和,最後陣列之和即原陣列的總和
當 n=8 的時候我們可以得到如上圖所示的執行過程,而如圖所示的層次結構稱為
二叉樹(將在後序章節學習)
,我們可以很容易發現原sum(lo, hi)被分為了sum(lo, mi)和sum(mi+1, hi)因此沒經歷一次遞迴操作我們的陣列區間的長度都會縮減為原來的一半.在本演算法下我們可以得知在經歷了 m=l
og2n
m=log_2n
m=log2
n次的遞迴呼叫後,陣列區間的長度會從最初的 n
nn 縮減至 1
11 因此我們可以得知本演算法的時間複雜度為 o(l
ogn)
o(logn)
o(logn
) 而在之前的線性遞迴的時間複雜度為 o(n
)o(n)
o(n)
所以二分遞迴更加優秀.
經典的遞迴問題,形如 1,1
,2,3
,5,8
,13.....
1,1,2,3,5,8,13.....
1,1,2,
3,5,
8,13
....
. 這樣的數列,叫做fibonacci數列
查詢fibonacci數列中的第 n
nn 個數我們可以用以下方法:
已知fibonacci數列的遞迴表示式為:f ib
(n)=
n\left( n\leq 1\right) \\ fib\left( n-1\right) +fib\left( n-2\right) \left( n\geq 2\right) \end
fib(n)
=但是我們不難發現採用此演算法需要執行 o(2
n)o(2^n)
o(2n
) 的時間,因此不適合在實際生活中運用,我們可以對演算法進行分析,可以發現列入在算第
8
個fibonacci數的時候,我們需要先行計算第6
個和第7
個fibonacci數,而在計算第7
個fibonacci數的時候會先計算第5
和第6
個fibonacci數,因此我們可以發現我們計算了 2遍 第6
個fibonacci數,所以進行了重複操作,因此我們可以採取一定優化策略即用時間換取空間,在各個子問題求解之後,借助一些儲存空間去記錄下對應的結果
我們可以從原問題出發,每當遇到乙個子問題的時候我們都優先檢驗該問題是否已經計算過,若已經計算過,我們直接調閱記錄獲得答案,從而避免重複計算
我們也可以從遞迴基出發,依次求出各子問題的解,直到最終求得原問題的解
第一種方法我們稱為
製表(tabulation)
或記憶(memoization)
第二種方法我們成為動態規劃(dynamic programming)
以下是兩種方法的c++**實現
long
long
fib(
int n,
long
long
&prev)
else
}
#include
using
namespace std;
long
long
fib(
int n)
return fib_num;
}
《遞迴入門》之回文
所謂回文字串,就是乙個字串,從左到右讀和從右到左讀是完全一樣的。比如 level aaabbaaa 題目 判斷乙個字串是否為回文 解法 遞迴 遞迴的作用在於把問題的規模不斷縮少,直到問題縮少到能簡單地解決 問 如何縮少問題規模?答 通過觀察可以知道,乙個回文字串其中內部也是回文。所以,我們只需要以去...
C語言 遞迴入門
遞迴是什麼,遞迴就是一種解決問題的方法 程式自身呼叫自身叫做遞迴。它的核心在於 大事化小!先舉幾個例子 1.接受乙個整型值,按順序列印它的每一位。只考慮正數 如 1234 應輸出1 2 3 4 1 先討論如果不遞迴該怎樣處理,一般步驟是這樣的,先判斷這個數是幾位數,然後在記錄下這個數的每一位,最後輸...
遞迴入門 走迷宮
有乙個nm格的迷宮 表示有n行 m列 其中有可走的也有不可走的,如果用1表示可以走,0表示不可以走,檔案讀入這nm個資料和起始點 結束點 起始點和結束點都是用兩個資料來描述的,分別表示這個點的行號和列號 現在要你程式設計找出所有可行的道路,要求所走的路中沒有重複的點,走時只能是上下左右四個方向。如果...