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