动态规划
- 求最优解
- 将一个大问题拆分成多个子问题
- 找出边界条件
- 分析递推转换公式
简单的例子:
爬楼梯问题
有一个n阶的楼梯,一次可以走1阶或者2阶,求计算出走到n阶公有多少方法?
例如:3阶 一共有三种走法
第一种:每次走一阶
第二种:第一次走1阶第二次走2阶
第三种:第一次走2阶第二次走1阶
function stepsOnStairs(n){
var stairs = [];
// 边界条件 走到1阶有1种方法,走到2阶有两种方法
stairs[1] = 1;
stairs[2] = 2;
for(var i=3;i<=n;i++){
// 递推公式,走到i阶的方法只有两种一种是从i-1走过来,另一种是i-2阶走过来,所以到i阶的方法总数和是两者相加
stairs[i] = stairs[i-1]+stairs[i-2];
}
return stairs[n];
}
硬币找零
假设有几种硬币,如1、3、5,并且数量无限。请找出能够凑齐数目为n的找零数所使用最少的硬币数。
假设c[i]表示找零为i时候需要用到的最少硬币数,那么存在c[i] = min(c[i-1],c[i-3],c[i-5]) + 1;
- 边界条件
c[0] = 0
- 递推公式
c[i] = Math.min.apply(null,[c[i-1],c[i-3],c[i-5]]) + 1
- 代码
function minChange(n){
var c = [],
temp = [];
//边界条件
c[0] = 0;
for(var i=1;i<=n;i++){
temp.length = 0;
if(i>=5){
temp.push(c[i-5]);
}else if(i>=3){
temp.push(c[i-3]);
}else{
temp.push(c[i-1])
}
c[i] = Math.min.apply(null,temp) + 1;
}
return c[n];
}
题外话。。
其实硬币问题有更简单的解法,假设要找零17那么最小的硬币数就是17先整除5,计下商3余数2,2除以3,计下商0余数2,2除以1,计下商2余数0。直到余数为0,把每一步的商做合计就是题解。3(5元)+2(2元) = 5枚;
总结:动态规划虽好,但有时候通过归纳或者其他直接方式能直接得出解的更优。