斐波那契数列算法--java三种解决方法

斐波那契数列算法–java三种解决方法

斐波那契数列描述:

斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N)在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从 1963 年起出版了以《斐波纳契数列季刊》为名的一份数学杂志,用于专门刊载这方面的研究成果。(摘自百度百科)*

三种方法:

1.递归(会重复计算一个值很多次)
2.递归优化(减少大量重复计算)
3.动态规划(只计算一次)

package com.lxf.demo1;

import java.util.ArrayList;

public class FeiBoPra {
    //计数
    private static int count=0;
    //存储每次计算后的值
    private static long[] longArray;

    public static void main(String[] args) {
        int n=30;//计算斐波那契数列的大小

        //斐波那契数列问题解决方式一(递归):
        //获取feibo1的开始时间
        long startMills1=System.currentTimeMillis();
        //System.out.println("startMills1 = " + startMills1);
        //执行feibo1函数,获取n斐波那契值
        long feibo1=feibo1(n);
        //获取feibo1的结束时间
        long endMills1=System.currentTimeMillis();
        //System.out.println("endMills1 = " + endMills1);
        //打印结果
        System.out.println("feibo1("+n+") = " + feibo1+",次数:"+count+",所花时间"+(endMills1-startMills1)/1000.0);



        //斐波那契数列解决方式二(递归优化):
        //将count归零
        count=0;
        //new一个存储结果的long数组
        longArray=new long[n];
        //获取feibo2的开始时间
        long startMills2=System.currentTimeMillis();
        //执行feibo2函数,获取n斐波那契值
        long feibo2=feibo2(n);
        //获取feibo2的结束时间
        long endMills2=System.currentTimeMillis();
        //打印结果
        System.out.println("feibo2("+n+") = " + feibo2+",次数:"+count+",所花时间"+(endMills2-startMills2)/1000.0);


        //斐波那契数列解决方式三(动态规划):
        //将count归零
        count=0;
        //获取feibo3的开始时间
        long startMills3=System.currentTimeMillis();
        //执行feibo3函数,获取n斐波那契值
        long feibo3=feibo3(n);
        //获取feibo2的结束时间
        long endMills3=System.currentTimeMillis();
        //打印结果
        System.out.println("feibo2("+n+") = " + feibo2+",次数:"+count+",所花时间"+(endMills2-startMills2)/1000.0);
    }


    //方法一:递归
    public static long feibo1(int n){
        //负数不处理
        if(n<=0){
            return 0;
        }
        //每运行一次count+1
        count++;
        //当n等于1或2时直接返回1
        if(n==1||n==2)
            return 1;
        //否则就返回前两个值的和
        return feibo1(n-1)+feibo1(n-2);
    }

    //方法二:递归优化
    public static long feibo2(int n){
        //负数不处理
        if(n<=0){
            return 0;
        }
        //每运行一次count+1
        count++;
        //当n等于1或2时直接返回1
        if(n==1||n==2)
            return 1;
        //每次判断是否已经计算过这个值了,没计算过继续向下计算
        if(longArray[n-1]==0)
            longArray[n-1]=feibo2(n-1)+feibo2(n-2);
        //计算过直接返回
        return longArray[n-1];
    }

    //方法三:动态规划
    private static long feibo3(int n) {
        //负数不处理
        if(n<=0){
            return 0;
        }
        //每运行一次count+1
        count++;
        //new 三个long值作为参数进行计算
        long a=1,b=1,temp=a+b;
        //循环计算,直到n为止
        for (int i = 2; i < n; i++) {
            //将a,b相加赋值给temp,例如:第一项+第二项=第三项...
            temp=a+b;
            //将a,b向后移动,例如:a换成第二项,b换成第三项。
            a=b;
            b=temp;
        }
        //返回结果
        return temp;
    }
}

注意:n太大第一种方法可能直接卡死,后面的方法就没法运行,建议分开运行

类似题型:

条件: f(n) = f(n-1)+f(n-2)+f(n-3)+1; f(0)=f(1)=f(2)=0。
问题: 计算f(100)、 f(100,000)、f(20,000,000)

package com.lxf.demo1;


//这里只用了动态规划
public class MyTest {
    public static void main(String[] args) {
        int n=4;//参数
        System.out.println("getResult("+n+") = " + getResult(n));
    }

    //计算f(n) = f(n-1)+f(n-2)+f(n-3)+1
    public  static long getResult(int n){
        if(n<0)
            return -1;
        if(n==0||n==1||n==2)
            return 0;
        //新建a,b,c三个long对象初值为0,temp用作计算a,b,c和。
        //a,b,c三个对象向后推算至n
        long a=0,b=0,c=0,temp=0;
        for (int i = 2; i < n; i++) {
            temp=a+b+c+1;
            b=c;
            a=b;
            c=temp;
        }
        //返回结果
        return temp;
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章