斐波那契數列算法--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;
    }

}

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