1. 程式人生 > >演算法(Java筆記)—遞推&遞迴求解斐波拉契數列

演算法(Java筆記)—遞推&遞迴求解斐波拉契數列

遞推演算法——理性思維模式的代表,其原理是根據已有的資料和關係,逐步推導而得到結果。

演算法的執行過程:

  1. 根據已知結果和關係,求解中間結果。
  2. 判定是否達到要求,未達到則繼續重複第一步,直到尋找到正確答案。

遞迴演算法——在程式中不斷地反覆呼叫自身來達到求解問題的方法,重點是呼叫自身

編寫遞迴方法時,必須使用if語句強制方法在未執行遞迴呼叫之前返回,如果不這樣做,它將永遠不會返回(這很重要)。

從理論上說,所有的遞迴函式都可以轉換為迴圈函式,然而代價通常都是比較高的。但遞迴是用棧機制實現的(c++),每深入一層,都要佔去一塊棧資料區域,對巢狀層數深的一些演算法,遞迴會力不從心,空間上會以記憶體崩潰而告終,而且遞迴也帶來了大量的函式呼叫,這也有許多額外的時間開銷。所以在深度大時,它的時空性就不好了。

遞迴呼叫分兩種情況:

  • 直接遞迴:就是指在方法呼叫方法本身。
  • 間接遞迴:指在另一個方法中呼叫遞迴方法(如前面提到的圖的遍歷),間接遞迴用的不多。

遞推與遞迴的區別:

  1. 從程式上看,遞迴表現為自己呼叫自己,遞推則沒有這樣的形式
  2. 一般來說,遞推的效率高於遞迴
  3. 遞迴最終求得問題是逆向的,遞推是從簡單問題出發,一步步的向前發展,最終求得問題。是正向的。

程式碼實現:

例項:斐波拉契數列(兔子產仔問題)——一對兩個月大的兔子以後每個月可以產仔一對,新生兔兩個月後又可以產仔,也就是說,一月份出生,三月份才可以產仔,假定兔子沒有死亡,問n月後兔子的數量;

分析:

  • 第一個月:1對兔子;
  • 第二個月:1對兔子;
  • 第三個月:2對兔子;
  • 第四個月:3對兔子;
  • 第五個月:5對兔子;
  • 即從第三個月開始,每個月的兔子對樹等於前兩個月的兔子數的總和;

遞推演算法求解:

// 遞推演算法例項——斐波拉契數列——兔子產仔問題(1,1,2,3,5,8,13...)
	int diTui2(int n) {// n表示月份
		int temp1, temp2, tempn;
		temp1 = 1;// 兩個月前的兔子對數
		temp2 = 1;// 一個月前的兔子對數
		tempn = 0;//n月的兔子對數
		for (int i = 3; i <= n; i++) {
			tempn = temp1 + temp2;
			temp1 = temp2;
			temp2 = tempn;
		}
		return tempn;
	}

遞迴演算法求解:

// 遞迴演算法例項——斐波拉契數列——兔子產仔問題(1,1,2,3,5,8,13...)
	int diTui(int n) {// n表示月份
		int temp1, temp2;
		if (n == 1 || n == 2) {
			return 1;
		} else {
			temp1 = diTui(n - 1);// 一個月前的兔子對數
			temp2 = diTui(n - 2);// 兩個月前的兔子對數
			return temp1 + temp2;
		}
	}

//遞迴演算法例項——階乘問題——如5!(5的階乘)=5x4x3x2x1=120;
	int  diGui(int n){
		if(n==1){
			return 1;
		}
		return n*diGui(n-1);
	}