数据结构与算法 —— 动态规划

Posted Dragon_GL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法 —— 动态规划相关的知识,希望对你有一定的参考价值。


简介

动态规划有时被认为是与递归相反的算法。 递归 是从问题的顶部开始,将一个完整的问题一步步分解成一个个子问题,通过解决掉所有分解出来的这些子问题的方式,来解决整个问题。动态规划 是从问题的底部开始,先解决掉底部的最简单的小问题,然后,通过已解的这些小问题作为基础合并成一个整体解决方案,从而解决掉整个大问题。

使用递归去解决问题虽然简洁,但 效率不高。包括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;
    

以上是关于数据结构与算法 —— 动态规划的主要内容,如果未能解决你的问题,请参考以下文章

动态规划算法--01背包问题

数据结构与算法 —— 动态规划

递归与动态规划

算法设计与分析-动态规划

算法导论-动态规划原理

算法1:动态规划