动态规划初步学习及理解

栏目: 编程工具 · 发布时间: 6年前

内容简介:最近又看到一篇文章,说到算法对前端的重要性,遂抽出时间(玩的时间),逼着自己看一些相关的知识,当看到动态规划相关文献时,也勾起了很大的兴趣,学习各位大神的博客,有了初步理解,借此记载,可能比较浅显,对于同样初学相关知识的同学,或许会有帮助,如有问题,望大神指出学习的最好方法便是带着问题学习,所以首先先采用网上普遍的、对理解动态规划很友好的一个问题作为学习切入点,问题解决后再总结归纳现在有10级台阶,每次只能上1级或2级台阶,问:到达10级台阶的方法有多少?

前言

最近又看到一篇文章,说到算法对前端的重要性,遂抽出时间(玩的时间),逼着自己看一些相关的知识,当看到动态规划相关文献时,也勾起了很大的兴趣,学习各位大神的博客,有了初步理解,借此记载,可能比较浅显,对于同样初学相关知识的同学,或许会有帮助,如有问题,望大神指出

正文

学习的最好方法便是带着问题学习,所以首先先采用网上普遍的、对理解动态规划很友好的一个问题作为学习切入点,问题解决后再总结归纳

问题:

现在有10级台阶,每次只能上1级或2级台阶,问:到达10级台阶的方法有多少?

解析:

首先按照正常逻辑,看到这个问题或许会懵,因为情况太多无从下手,但是最优解往往需要更改思考方式

  1. 这里可以从结果考虑,最后我们踩在第10级台阶上,由于每次只能上1 或 2级台阶,所以上一步,我门应该在第9级台阶,或第8级台阶;
  2. 基于1的结论,从0 到 9 级台阶有多少种方法,对应的从9 到 10级台阶就有多少种方法(这里需要理解下),同理从0 到 8级台阶的方法总数等于从8 到 10级台阶的方法总数,可得从0 到 10级台阶的方法总数(以下简称methods(10))等于 从0 到 9级台阶的方法总数 加 从0 到 8级台阶的方法总数,即methods(10) = methods(9) + methods(8);这里的methods(9) 和 methods(8)就是methods(10)的 最优子结构 (思维导图有点大,只展示一部分) 动态规划初步学习及理解
  3. 从第2点我门已经发现了问题的解决逻辑和一点思路,按照第2点的思路,我们将以二叉树的形式将问题分裂成“无数”的子问题,直到分裂成 methods(2) 和 methods(1)时,methods(2)(从0 到 2级台阶的方法数)等于2,而methods(1)等于1,这里的methods(2) 和 methods(1)也就是动态规划里 边界
  4. 由3的结论,我们只需要将所有子问题的解相加便是问题结果,这里将思路转为代码,通过递归实现, methods(n) = methods(n - 1) + methods(n - 2),methods(n - 1) = ......,以此类推
function methods(n) {

    if (n == 1) return 1
    
    if (n == 2) return 2
    
    console.log('计算')
    
    return methods(n - 1) + methods(n - 2)
  }

  console.log(methods(10)); // 89

问题到这看似已经解决了,但是我想同学在思维导图中应该也发现了,很多子问题是重复的,但是上面代码却做了很多重复工作,很浪费 冗余(如下图),我们希望已经计算过的就不要在重复计算

动态规划初步学习及理解

所以优化下, 保存计算过的结果:

var resultList = [] // 保存计算过的结果,以计算的台阶数做索引下标

  function methods(n) {

    if (n == 1) return 1
    if (n == 2) return 2
    if (!resultList[n]) { // 没有就保存
      console.log('计算', n)
      resultList[n] = methods(n - 1) + methods(n - 2)
    }
    return resultList[num]
  }

动态规划初步学习及理解

这样看,就节省了很多计算,台阶总数越大,越明显

然后咱们再精简下代码:

var resultList = [0, 1, 2]; // 对于本题的结果预存了,方便点

  function fnSumF(n) {
  
    if (!resultList[n]) resultList[n] = fnSumF(n - 1) + fnSumF(n - 2);
  
    return resultList[n]
  }

总结

动态规划的英文名是Dynamic Programming,是一种分阶段求解决策问题的数学思想;与分治方法类似,都是通过组合子问题的解来来求解原问题的。再来了解一下什么是分治方法,以及这两者之间的差别,分治方法将问题划分为互不相交的子问题,递归的求解子问题,再将它们的解组合起来,求出原问题的解。而动态规划与之相反,动态规划应用与子问题重叠的情况,即不同的子问题具有公共的子子问题(子问题的求解是递归进行的,将其划分为更小的子子问题)。在这种情况下,分治方法会做许多不必要的工作,他会反复求解那些公共子子问题。而动态规划对于每一个子子问题只求解一次,将其解保存在一个表格里面,从而无需每次求解一个子子问题时都重新计算,避免了不必要的计算工作。

其实关于和分治的区别,在我们解决问题优化时已经可以看出

初学的浅层理解,如有问题希望大家指出,指点,如果问题或者好文章,也希望可以评论推荐

学的越多,才发现自己懂得越少


以上所述就是小编给大家介绍的《动态规划初步学习及理解》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Programming PHP

Programming PHP

Rasmus Lerdorf、Kevin Tatroe、Peter MacIntyre / O'Reilly Media / 2006-5-5 / USD 39.99

Programming PHP, 2nd Edition, is the authoritative guide to PHP 5 and is filled with the unique knowledge of the creator of PHP (Rasmus Lerdorf) and other PHP experts. When it comes to creating websit......一起来看看 《Programming PHP》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

随机密码生成器
随机密码生成器

多种字符组合密码

MD5 加密
MD5 加密

MD5 加密工具