计算斐波那契数最容易理解的一种方法就是递归,具体实现方法如下所示:
public static int fib(int n){
if(n<=1)
return 1;
else
return fib(n-1)+fib(n-2);
}
在这个算法中我们可以得知,运行时间T(n)不小于T(n-1)与T(n-2)之和,所以,该算法的运行时间是指数级增长的。
由于计算F(n)只需要F(n-1)与F(n-2),因而,我们可以有如下线性算法:
public static int lineFib(int n){
if(n<=1)
return 1;
int last = 1;
int nextToLast = 1;
int answer = 1;
for(int i = 2;i<=n;i++){
answer = last+nextToLast;
nextToLast = last;
last = answer;
}
return answer;
}
下面我们来比较这两种算法的运行时间:
public static void main(String[] args) {
// TODO Auto-generated method stub
int n = 40;
long start = System.currentTimeMillis();
int a = fib(n);
long t1 = System.currentTimeMillis();
int b = lineFib(n);
long t2 = System.currentTimeMillis();
System.out.println("递归方法所求结果: "+a+" ,用时: "+(t1-start)+"毫秒");
System.out.println("线性算法所求结果: "+b+" ,用时: "+(t2-t1)+"毫秒");
}
当n取40时,运行截图如下
可以看出两种算法的差别还是挺大的,根据这个结果估计用我的这台电脑用递归的方法来计算n=100时的结果的话就得需要2的50多次方秒了,当然,那时就不能用int类型来存储计算结果了,实际上当n取70多的时候用int类型就已经成不下结果溢出了。
那么为什么两种方法的差别这么大呢?我们看到,在计算F(n)的时候,我们需要计算一次F(n-1)和F(n-2),在计算F(n-1)的時候,我們需要計算F(n-2)和F(n-3),这里就存在两次计算F(n-2),继续追踪的话就会发现F(n-3)计算了3次,F(n-4)计算了5次,而F(n-5)计算了8次,冗余的计算是爆炸性增长的,因而递归计算的时间复杂度也是爆炸性增长的。而线性算法中每一个的值只计算一次,因而差距也就相当明显了