递归算法实现斐波那契数列

假定兔子在出生两个月后,就有繁殖能力,一对兔子每个月能生出一对小兔子来。如果所有兔子都不死,那么一年以后可以繁殖多少对兔子?

这就是著名的斐波那契数列,也称作兔子数列。

一、问题分析

刚开始,有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))均是最低的。

猜你喜欢

转载自blog.csdn.net/LIAO_7053/article/details/82352919