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