八-0, Java实现斐波那契数的三种方式(递推, 数组, 递归)

1.原理和定义

斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为 “兔子数列”。

如下图所示,就是一个斐波那契数列:
在这里插入图片描述

在数学上,斐波那契数列被以如下递推的方法定义:

在这里插入图片描述

从斐波那契的递推公式我们可以总结出重要一点:斐波那契数列从第三项开始,每一项都等于前两项之和。

2. 递推方式实现斐波那契数列

public class FibonacciImp_3 {
    //最简单的循环递推相加法
    public static int getFibonacci(int n){
        int a=1, b=1, c=0;
        if(n==0) return 0;
        if(n==1 || n==2) return 1;

        // n>2 时, 我们利用a,b,c 的递推得出需要的斐波那契数
        // 由于第一次我们从 c = a+b = 2开始的, n>2的斐波那契数我们需要递推(连加)n-2次
        //例如: F(4)-->
        /**
         * 第一次: c=a+b=2,a=1,b=2 f3
         * 第二次: c=a+b=3,a=2,b=3 f4
         * 第三次: c=a+b=5,a=3,b=5 f5
         * 第四次: c=a+b=8,a=5,b=8 f6
         */
        for(int i=0; i<n-2; i++){
            c = a+b;
            a = b; // a,b后移
            b = c;
        }
        return c;

    }

    public static void main(String[] args) {
        for(int i=0; i<=20; i++){
            System.out.println("斐波那契数: F("+i+")= "+getFibonacci(i));
        }
    }

3. 数组方式实现斐波那契数列

public class FibonacciImp {
    /**
     * 使用数组实现斐波那契
     */
    public static int[] getFibonacci(int maxSize){
        int[] fib = new int[maxSize+1];
        //因为我们用给定的f(n)中的n+1去初始化数组
        // 所以n=0,或是n=1会发生数组的越界
        // 所以我们需要做以下处理
        if(fib.length >= 1)  fib[0] = 0;
        if(fib.length >= 2 ) fib[1] = 1;

        //注意, 斐波那契f(10)为数列的第11个数, 数列此时的长度为11
        for(int i=2; i<= fib.length-1; i++){
            fib[i] = fib[i-1] + fib[i-2];
        }
        return fib;
    }

    public static void main(String[] args) {

            System.out.println(Arrays.toString(getFibonacci(20)));

    }
}

4. 递归方式实现斐波那契数列

public class FibonacciImp_1 {
    /**
     * 递归实现斐波那契
     */
    public static int getFibonacci(int n){
        //起始的两个值
        if(n==0) return 0;
        if( n==1 || n==2) return 1;

        //递归
        if( n>2 )
        return getFibonacci(n-1)+getFibonacci(n-2);
        //递归出口
        return -1;// n的值不为1,2,或者大于2
    }

    public static void main(String[] args) {
        for(int i=0; i<=50; i++){
            System.out.println("斐波那契数: F("+i+")= "+getFibonacci(i));
        }
    }
}

递归的实现方法最简单,也是很容易就能想到的。但是效率太低了,当n>=40时,你会发现计算时间明显变长,当n接近50时,idea运行窗口等了半天才反应过来。
注意:由于int的取值范围有限,最大值为 (2^32)-1 = 2147483647,当n>46的时候,会发生取值范围溢出的情况,所以这里如果想要验证n>46时的计算耗时情况,请将返回值类型int改为long。

posted @ 2022-05-26 20:31  青松城  阅读(144)  评论(0编辑  收藏  举报