1. 程式人生 > >遞迴演算法實現斐波那契數列

遞迴演算法實現斐波那契數列

假定兔子在出生兩個月後,就有繁殖能力,一對兔子每個月能生出一對小兔子來。如果所有兔子都不死,那麼一年以後可以繁殖多少對兔子?

這就是著名的斐波那契數列,也稱作兔子數列。

一、問題分析

剛開始,有1對幼兔,兔子總對數為1;

經過一個月後,幼兔長為小兔,兔子總對數為1;

經過二個月後,幼兔長大為成年兔子,並生出1對幼兔,兔子總對數為2對;

經過三個月後,成年兔子兔子再生出1對幼兔,幼兔長大為小兔,兔子總對數達到3對;

        -------------------------------------------

依次類推可以得到下表:

月份

0 1 2 3 4 5 6 ...
幼兔對數

1

0 1 1 2 3 5 ...
小兔對數 0 1 0 1 1 2 3 ...
成兔對數 0 0 1 1 2 3 5 ...
總對數 1 1 2 3 5 8 13 ...

根據上表可以發現,對於兔子總對數,從第三項開始,每一項均為前兩項之和。

二、斐波那契數列

在數學上,斐波納契數列以如下被以遞推的方法定義:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*),

下面讓我們通過遞迴演算法來求解這個兔子數列吧。

三、不同演算法實現

package com.liao.algorithm;

import java.util.Scanner;

public class Recursion {
	private static int a;//輸入月份數
	static int t1, t2, t3;//統計程式碼執行次數

	public static void main(String[] args) {
		while (a <= 0) {
			System.out.println("請輸入經過月份(1~n):");
			a = new Scanner(System.in).nextInt();
		}
		System.out.println(a + "個月後,兔子總數為:" + fib1(a) + ",執行次數:" + t1);
		System.out.println(a + "個月後,兔子總數為:" + fib2(1, 1, a) + ",執行次數:" + t2);
		System.out.println(a + "個月後,兔子總數為:" + fib3(1, 1, a) + ",執行次數:" + t3);
	}

	// 遞迴實現
	public static int fib1(int n) {
		t1++;
		if (n < 3)
			return 1;
		return fib1(n - 1) + fib1(n - 2);
	}

	// 尾遞迴實現
	public static int fib2(int fir, int sen, int n) {
		t2++;
		if (n < 3)
			return 1;
		if (n == 3)
			return fir + sen;
		return fib2(sen, fir + sen, n - 1);
	}

	// 迭代實現
	public static int fib3(int fir, int sen, int n) {
		int total = 1;
		if (n < 3)
			return total;
		while (n > 2) {
			t3++;
			total = fir + sen;
			fir = sen;
			sen = total;
			n--;
		}
		return total;
	}
}

四、執行結果

五、分析小結

1、三種演算法都得到了一樣的結果,但是有一個地方有非常大的區別,那就是程式碼執行次數上,或者說是空間複雜度。

2、遞迴演算法即第一種方法,程式碼看著最簡潔,但其重複運算次數太多,運算效率低,其時間複雜度為O(2^n),空間複雜度為O(n);

3、尾遞迴演算法將每一次的計算結果作為引數傳入方法,減少不必要的重複運算,運算效率大幅提高,時間複雜度為O(n);

4、迭代演算法即第三種演算法,是通過我們常用的迴圈判斷語句實現,由於僅建立了 4個基礎變數,通過賦值傳遞數值,時間複雜度(O(n))和空間複雜度(O(1))均是最低的。