简介
动态规划有时被认为是与递归相反的算法。 递归 是从问题的顶部开始,将一个完整的问题一步步分解成一个个子问题,通过解决掉所有分解出来的这些子问题的方式,来解决整个问题。动态规划 是从问题的底部开始,先解决掉底部的最简单的小问题,然后,通过已解的这些小问题作为基础合并成一个整体解决方案,从而解决掉整个大问题。
使用递归去解决问题虽然简洁,但 效率不高。包括JavaScript 在内的众多语言,不能高效地将递归代码解释为机器代码,尽管写出来的程序简洁,但是执行效率低下。但这并不是说使用递归是件坏事,本质上说,只是那些指令式编程语言和面向对象的编程语言对递归的实现不够完善,因为它们没有将递归作为高级编程的特性。
动态规划实例
1 > . 计算斐波那契数列
什么是斐波那契数列?
斐波那契数列可以简单的理解为下面这一组序列,
0,1, 1,2,3, 5, 8,13,21, 34,55 … … … . .
你会发现,上面这一组数字的规律,即从第三项起每一项都是前面两项的和。
下面,先看看使用递归实现的计算斐波那契数列的代码:
function Fib(n) {
if (n < 2) {
return 1;
} else {
return Fib(n-2) + Fib(n-1);
}
}
console.log( Fib( 10 ) ); // 55
接着,我们来看看使用动态规划来实现的计算斐波那契数列的代码实现:
function Fib(n) {
var arr = [];
for (var i = 0; i < n; i++) {
arr[i] = 0;
}
if (n == 1 || n == 2) {
return 1;
} else {
arr[1] = 1;
arr[2] = 1;
for (var i = 3; i <= n; i++) {
arr[i] = arr[i-2] + arr[i - 1];
}
return arr[n - 1];
}
}
console.log( Fib(10) ); // 55
使用动态规划设计的算法,通过先解决最简单的子问题,之后,利用已解决的子问题的解区解决更复杂的问题,从而一步步 解决整个问题。
所有子问题的解都被存贮在一个数组里,以便之后需要的时候访问。
总结
通过观察比较两种方法实现的执行效率可以看出,使用动态规划的算法实现更加高效。
补充:
其实,我们还有一种方法来实现计算斐波那契数列的目的。那就是使用迭代的方式来实现,实现代码如下:
function Fib(n) {
var result = 0,
last = 1,
nextLast = 1;
if (n < 2) {
return 1;
} else {
for (var i = 2; i < n; i++) {
result = arr[i-2] + arr[i-2];
last = nexLast;
nextLast = result;
}
return result;
}
}