动态规划一:斐波那契数列
方法一:递归方法
public long fib(int n){
if(n == 0) return 0;
if(n == 1) return 1;
return fib(n-1)+fib(n-2);
}
以fib(5)为例:
深色部分的fib(3),以及fib(2)会被重复计算,当n增大时,递归树高度增加,会有更多的重复计算;因此这种递归方法的效率非常低;考虑到递归方法,会有重复计算的缺点,因此考虑设定一个数组,保存之前计算的结果,访问fib(n)时,先查看数组中对应位置的值是否存在,若存在则直接返回,若不存在,则计算后,保存到对应位置,然后返回;详见方法二:
方法二:记忆化搜索
//将数组 temp 定义为类变量,temp[i]表示fib(i)的值
long [] temp = new long[n+1];
public long fib(int n,long[] temp){
if(n == 0) return 0;
if(n == 1) return 1;
if(temp[n] == 0)
//记忆化搜索,自上向下
temp[n] = fib(n-1,temp)+fib(n-2,temp);
return temp[n];
}
方法二用数组temp保存了每一步的计算结果,实现了自上向下的记忆化搜索,避免了大量的重复计算;
方法三:动态规划
//将数组 temp 定义为类变量,temp[i]表示fib(i)的值
long [] temp = new long[n+1];
public long fib(int n,long[] temp){
temp[0] = 0;
temp[1] = 1;
//动态规划,自底向上
for(int i = 2;i <= n;i++)
temp[i]=temp[i-1]+temp[i-2];
return temp[n];
}
方法四:动态规划改进
public long fib(int n){
long temp0 = 0;
long temp1 = 1;
long temp2 = temp0+temp1;
for(int i = 2;i <= n;i++){
temp2 = temp1+temp0;
temp0 = temp1;
temp1 = temp2;
}
return temp2;
}
动态规划简介:
图中的重叠子问题,是指在减小问题规模过程中,会有多次重复的操作;例如前文方法一递归方法中提到的多次重复计算;最优子结构是指在求解最优化问题时在问题规模减小过程中,原来规模的最优化问题可以转化为子问题的最优化问题。详见《动态规划二:整数划分求积》。针对重叠子问题和最优子结构问题,有两种解决方法:记忆化搜索(自顶向下);动态规划(自底向上)。