因为Fibonacci数是递归定义的,写一个计算Fn 的递归程序似乎是很自然的事情,但是如果用到了Fibonacci的递归的话,就会产生一个很严重的问题,首先计算F40需要432 毫秒,看似很少,但是,这个Fibonacci数基本的计算只要39次加法,而对于计算机来说,普通的计算机一毫秒就能计算上千万次。
究其原因就是这个递归的过程执行了冗余的计算,为计算Fi(n),我们递归计算Fi(n-1),递归调用返回时我们通过另一个递归调用计算Fi(n-2)。但是我们计算Fi(n-1)的过程中已经计算了Fi(n-2),因此,对Fi(n-2)的调用是浪费的。
对Fibonacci数的计算如下图
public class Main {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
int z = reFibonacci(40);
long endTime = System.currentTimeMillis();
System.out.println(z+" CurrentTime: "+(endTime-startTime));
}
private static int reFibonacci(int i) {
if(i<=1) return i;
else return reFibonacci(i-1)+reFibonacci(i-2);
}
}
运行结果:102334155 CurrentTime: 432
上面是采用递归的算法,为了突出递归的严重问题,下面我用数组计算。
public class Main {
private static long[] fib = new long[1000];
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
fib[0] = 0;
fib[1] = 1;
for(int i =2;i<=40;i++) {
fib[i] = fib[i-1]+fib[i-2];
}
long endTime = System.currentTimeMillis();
System.out.println(fib[40]+" CurrentTime: "+(endTime-startTime));
}
}
运行结果是: 102334155 CurrentTime: 0
大家可以看到,代码并不显得很长,但是相对于计算机的空间来说,就小很多了
因为,用数组来计算的结果,电脑运行时间已经忽略不计了。所以递归不一定就是很好用的方法,只能说用相对的方法更好