三种方法分别适用的数据量范围(即n的取值)如下
常规:1-50
记忆华搜索:1-5000
动态规划:1-50000
package com.demo;
import java.math.BigInteger;
public class Fibonacci {
public static long[] memo = new long[123457];
/**
* 常规:斐波那契
* 下面代码的特点,两个return
* 用 int 作为返回值的原因是这种方法根本算不了多少数就顶不住了,
* 数据量大一点就慢的要命了,再大一点就爆栈了
* 所以int 范围就够了
*/
public static int fibo(int n) {
if(n==1 || n==2)
return 1;
return fibo(n-1)+fibo(n-2);
}
/**
* 记忆化搜索:斐波那契
* 下面代码的特点,两个return,夹一个递归赋值操作
* 用 long 作为返回值的原因是这种方法虽然能很快的算很多数,
* 但数据量再大一点就爆栈了
* 所以long 范围就够了
*/
public static long memoFibo(int n) {
if(n == 1 || n == 2)
return 1;
if(memo[n] == 0) // 代表 fibo(n) 未被计算过
memo[n] = memoFibo(n-1)+memoFibo(n-2);
return memo[n];
}
/**
* 动态规划:斐波那契
* 下面代码的特点,内部申请数组,for循环计算,一个return
* 之所以是一个return,区别于上面两个return,就是因为此方法不是递归,不需要递归结束条件
* 用BigInteger作为返回值的原因是这种方法能算很多数,
* 数据量可以撑到Java堆内存不足
* 所以使用BigInteger
*/
public static BigInteger dpFibo(int n) {
BigInteger[] memory = new BigInteger[n+1];
memory[1] = BigInteger.valueOf(1);
memory[2] = BigInteger.valueOf(1);
for(int i=3; i<=n; i++) // 注意结束条件是小于等于
memory[i] = memory[i-1].add(memory[i-2]); // 注意索引是i不是n
return memory[n];
}
public static void main(String[] args) {
int n = 20;
// n > 45 时会很慢
long s = System.nanoTime();
int res = fibo(n);
long e = System.nanoTime();
// n > 1w 时虽然很快,但long越界,再大就会爆栈
long sMemo = System.nanoTime();
long resMemo = memoFibo(n);
long eMemo = System.nanoTime();
// n > 10w 时会java.lang.OutOfMemoryError: Java heap space
long sDp = System.nanoTime();
BigInteger resDp = dpFibo(n);
long eDp = System.nanoTime();
System.out.println(res+"fibo用时:"+(e-s)/1000+"μs");
System.out.println(resMemo+"memoFibo用时:"+(eMemo-sMemo)/1000+"μs");
System.out.println(resDp+"dpFibo用时:"+(eDp-sDp)/1000+"μs");
}
}

博客介绍了计算Fibonacci的三种方法适用的数据量范围。常规方法适用于n取值1 - 50,记忆化搜索适用于n取值1 - 5000,动态规划适用于n取值1 - 50000。
1763

被折叠的 条评论
为什么被折叠?



