package com.zengwen.ten;
public class FibDemo {
//用于统计斐波那契函数的执行次数
static int count;
public static void main(String[] args) {
//测试斐波那契数列
//规模为20
int n = 20;
long startTime=System.currentTimeMillis();
long num = fib(n);
long endTime=System.currentTimeMillis();
float excTime=(float)(endTime-startTime);
System.out.println(num);
System.out.println("执行时间:"+excTime+"ms");
System.out.println("fib()执行次数"+count);
}
public static long fib(int n){
count++;
if (n == 0) return 0;
if (n == 1) return 1;
return fib(n - 1) + fib(n - 2);
}
}
在规模为20的情况下,执行时间为1.0ms,fib()执行了21891次
在规模为40的情况下,执行时间为701.0ms,fib()执行了331160281次
在规模为80的情况下,本人等了很久机子没啥反应了.......
通过数据可以看出,显然,斐波那契它的时间复杂度应该是一个0(R^n)的指数级别算法。
下面对它里面的细节进行讨论,如图:
拿计算fib(5)的过程进行说明,fib(3)是算了2次,fib(2)算了3次,如果规模更大,那么这种重复的计算量将会非常非常大了。
用一个数组保存fib(0)~fib(n)之间所有的数值,一旦再需要这个fib(n)值直接取数组中的值即可,不用再次计算。
package com.zengwen.ten;
import java.util.ArrayList;
import java.util.HashMap;
public class FibDemo {
//用于统计斐波那契函数的执行次数
static int count;
public static void main(String[] args) {
//测试斐波那契数列
//规模为80
int n = 20;
long[] memo = new long[n+1];//存放斐波那契fib(0)~fib(5)
for (int i = 0; i < memo.length; i++) {
memo[i] = -1;
}
long startTime=System.currentTimeMillis();
long num = fib(n,memo);
long endTime=System.currentTimeMillis();
float excTime=(float)(endTime-startTime);
System.out.println(num);
System.out.println("执行时间:"+excTime+"ms");
System.out.println("fib()执行次数"+count);
}
public static long fib(int n,long[] arr){
count++;
if (n == 0) return 0;
if (n == 1) return 1;
if (arr[n] == -1){
arr[n] = fib(n - 1,arr) + fib(n - 2,arr);
}
return arr[n];
}
}
修改过后,发现在规模1000的情况下,执行次数直接降为1999,时间1.0ms