递归算法及经典例题详解
大部分人在學習編程時接觸的第一個算法應該就是遞歸了,遞歸的思想其實很好理解,就是將一個問題拆分為若干個與本身相似的子問題,通過不斷調用自身來求解。
但很多新手在實際操作中卻很難正確使用到遞歸,有時面對問題還會有種無從下手的感覺,在此,我總結了一些解決遞歸問題的方法和思路,希望對你能有所幫助。
1.什么是遞歸
遞歸簡單來說就是在運行過程中不斷調用自己,直到碰到終止條件,返回結果的過程。
遞歸可以看作兩個過程,分別是遞和歸。遞就是原問題把要計算的結果傳給子問題;歸則是子問題求出結果后,把結果層層返回原問題的過程。
下面設一個需要經過三次遞歸的問題,為大家詳細看一下遞歸的過程:
當然,現實中我們遇到遞歸問題是不會按照圖中一樣一步一步想下來,主要還是要掌握遞歸的思想,找到每個問題中的規律。
2.什么時候使用遞歸
遞歸算法無外乎就是以下三點:
1.大問題可以拆分為若干小問題
2.原問題與子問題除數據規模不同,求解思路完全相同
3.存在遞歸終止條件
而在實際面對遞歸問題時,我們還需要考慮第四點:當不滿足終止條件時,要如何縮小函數值并讓其進入下一層循環中
3.遞歸的實際運用(階層計算)
了解了大概的思路,現在就要開始實戰了。下面我們來看一道經典例題:
求N的階層。
首先按照思路分析是否可以使用遞歸算法:
滿足條件,可以遞歸:
public static int Factorial(int num){if(num==1){return num;}return num*Factorial(num-1);}而最后的return,便是第四步,縮小參數num的值,讓遞歸進入下一層。
一般來說,第四步往往是最難的,需要弄清該如何縮小范圍,如何操作返回的數值,這一步只能通過不斷地練習提高了(當然如果你知道問題的數學規律也是可以試出來的)。
4.其它遞歸例題:
一:順序打印,當輸入一個整數時,按順序依次打印每一位的值
該題可以理解為不斷拆分整數的最大位,并將它們一一打印。與求階層不同的是,該題的遞歸是在終止條件里進行的。
令num不斷除10,最后只剩下最高位時并打印。
而在輸出時%10,是因為當最高位打印返回后,繼續打印的數不一定是個位數,%10只保留個位。
public static void PrintNumber(int num){if (num>10){PrintNumber(num/10);}System.out.print(num%10+",");}二:斐波那契數列:有一個數列:1、1、2、3、5、8、13、21、34…,求該數列的第 n 項的值是多少。
有了以上兩個例子,這樣的遞歸問題就很好解決了。
首先我們觀察斐波那契數列的規律是N=(N-1)+(N-2),要保證返回值不為0,所以有兩個終止條件。
public static int Fibonacci(int num){if (num==1||num==2){return 1;}return Fibonacci(num-1)+Fibonacci(num-2);}之后讓我們再來看看遞歸的應用問題,與數學問題相比,在做應用題前需要先將題轉換為數學問題,找到規律后再進行代碼編寫。
三 :漢諾塔(Tower of Hanoi)源于印度傳說中一個古老的益智玩具。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。并且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。
漢諾塔問題算是遞歸算法的經典例題了,很多初學者的入門題就是它。
在剛看到漢諾塔的時候,相信很多人都是一頭霧水,不知道如何下手。其實面對應用題的時候,先建立它的模型,弄清題意后,再尋找其中的數學規律,解題思路便會清晰不少。
1.首先,題目的意思就是一個柱子A上有64的按大小順序放置的圓片,要全部移動到另一根柱子C上,每次只能移動一個,可以借助柱子B,且小的不能在大的下面。求最少的移動次數。
2.然后,尋找其中的數學規律(數學歸納法)。
先讓所有圓片從上到下按1到N排序。
當N=1時,只需從A->C,移動1次。
當N=2時,先讓1號從A->B,再讓2號從A->C,最后讓1號從B->C,移動3次。
當N=3時,可以理解為先讓1、2號從A->B,再讓3號從A->C,最后讓1、2號從B->C。因為由N=2可以得知,移動兩片需要3次,而A->B,B->C共進行了兩次,所以共有6次,再加上3號A->C的過程,要移動7次。
同理,當N=4時,共要移動2×7(N=3的移動次數)+1=15次。
…
所以,當N=N時,要移動2×(N-1)的移動次數+1次
(其實也可以看做2的N次方-1)
至此,得到了該題的規律,代碼便好些多了。
public static int TowerOfHanoi(int num){if (num==1){return 1;}return TowerOfHanoi(num-1)*2+1;}四:青蛙跳臺階問題:一只青蛙一次可以跳1級或2級臺階,求該青蛙跳N級的臺階總共有多少種跳法。
有了漢諾塔的經驗,這道題做起來就很順利了
先分析題意,再總結數學規律(本題題意簡單,就直接開始數學歸納了)
當N=1,1種跳法。
當N=2,2種跳法。
當N=3,青蛙第一次跳的時候,它只有兩種選擇:跳1級,剩兩級臺階,即N=2,有2種跳法;跳2級,剩一級臺階,即N=1,1種跳法。 所以,N3的跳法=N2+N1。
所以,N4=N3+N2
…
其實現在你一定會發現,青蛙跳臺階問題和斐波那契額數列的數學規律是一樣的,分析清楚之后,代碼也就寫出來了:
public static int FrogJumpSteps(int num){if (num==1){return 1;}if (num==2){return 2;}return FrogJumpSteps(num-1)+FrogJumpSteps(num-2);}5.總結
到此,基本把遞歸算法的基礎為大家講了一遍。當然,我說的只是最基礎的部分,遞歸算法在之后還有很多變式,如:如何避免重復運算,如何自下而上操作等等。
最后,祝大家在編程的道路上越走越遠。
大鵬一日同風起,扶搖直上九萬里。
總結
以上是生活随笔為你收集整理的递归算法及经典例题详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对链表的插入操作
- 下一篇: 【好用的ORM框架】