动态规划套路详解 .pdfVIP

  1. 1、本文档共5页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  5. 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  6. 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  7. 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  8. 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多

动态规划套路详解

读完本⽂,你可以去⼒扣拿下如下题⽬:

这篇⽂章是我们号半年前⼀篇200多赞赏的成名之作「动态规划详解」的进阶版。由于账号迁移的原因,旧⽂⽆法被搜索到,所以我润⾊了

本⽂,并添加了更多⼲货内容,希望本⽂成为解决动态规划的⼀部「指导⽅针」。

动态规划问题(DynamicProgramming)应该是很多读者头疼的,不过这类问题也是最具有技巧性,最有意思的。本书使⽤了整整⼀个章节

专门来写这个算法,动态规划的重要性也可见⼀斑。

刷题刷多了就会发现,算法技巧就那⼏个套路,我们后续的动态规划系列章节,都在使⽤本⽂的解题框架思维,如果你⼼⾥有数,就会轻松

很多。所以本⽂放在第⼀章,来扒⼀扒动态规划的裤⼦,形成⼀套解决这类问题的思维框架,希望能够成为解决动态规划问题的⼀部指导⽅

针。本⽂就来讲解该算法的基本套路框架,下⾯上⼲货。

⾸先,动态规划问题的⼀般形式就是求最值。动态规划其实是运筹学的⼀种最优化⽅法,只不过在计算机问题上应⽤⽐较多,⽐如说让你求

最长递增⼦序列呀,最⼩编辑距离呀等等。

既然是要求最值,核⼼问题是什么呢?求解动态规划的核⼼问题是穷举。因为要求最值,肯定要把所有可⾏的答案穷举出来,然后在其中找

最值呗。

动态规划这么简单,就是穷举就完事了?我看到的动态规划问题都很难啊!

⾸先,动态规划的穷举有点特别,因为这类问题存在「重叠⼦问题」,如果暴⼒穷举的话效率会极其低下,所以需要「备忘录」或者「DP

table」来优化穷举过程,避免不必要的计算。

⽽且,动态规划问题⼀定会具备「最优⼦结构」,才能通过⼦问题的最值得到原问题的最值。

另外,虽然动态规划的核⼼思想就是穷举求最值,但是问题可以千变万化,穷举所有可⾏解其实并不是⼀件容易的事,只有列出正确的「状

态转移⽅程」才能正确地穷举。

以上提到的重叠⼦问题、最优⼦结构、状态转移⽅程就是动态规划三要素。具体什么意思等会会举例详解,但是在实际的算法问题中,写出

状态转移⽅程是最困难的,这也就是为什么很多朋友觉得动态规划问题困难的原因,我来提供我研究出来的⼀个思维框架,辅助你思考状态

转移⽅程:

明确basecase-明确「状态」-明确「选择」-定义dp数组/函数的含义。

按上⾯的套路⾛,最后的结果就可以套这个框架:

#初始化basecase

dp[0][0][...]=base

#进⾏状态转移

for状态1in状态1的所有取值:

for状态2in状态2的所有取值:

for...

状态dp[1][状态2][...]=求最值(选择1,选择2...)

下⾯通过斐波那契数列问题和凑零钱问题来详解动态规划的基本原理。前者主要是让你明⽩什么是重叠⼦问题(斐波那契数列没有求最值,

所以严格来说不是动态规划问题),后者主要举集中于如何列出状态转移⽅程。

⼀、斐波那契数列

请读者不要嫌弃这个例⼦简单,只有简单的例⼦才能让你把精⼒充分集中在算法背后的通⽤思想和技巧上,⽽不会被那些隐晦的细节问题搞

的莫名其妙。想要困难的例⼦,历史⽂章⾥有的是。

1、暴⼒递归

斐波那契数列的数学形式就是递归的,写成代码就是这样:

intfib(intN){

if(N==1||N==2)return1;

returnfib(N-1)+fib(N-2);

}

这个不⽤多说了,学校⽼师讲递归的时候似乎都是拿这个举例。我们也知道这样写代码虽然简洁易懂,但是⼗分低效,低效在哪⾥?假设n

=20,请画出递归树:

PS:但凡遇到需要递归的问题,最好都画出递归树,这对你分析算法的复杂度,寻找算法低效的原因都有巨⼤帮助。

这个递归树怎么理解?就是说想要计算原问题,我就得先计算出⼦问题和,然后要计算,我就要先算出⼦问题和

f(20)f(19)f(18)f(19)f(18)

,以此类推。最后遇到或者的时候,结果已知,就能直接返回结果,递归树不再向下⽣长了。

f(17)f(1)f(2)

递归算法的时间复杂度怎么计算?就是⽤⼦问题个数乘以解决⼀个⼦问题需要的时间。

⾸先计算⼦问题个数,即递归树中节点的总数。显然⼆叉树节点总数为指数级别,所以⼦问

您可能关注的文档

文档评论(0)

182****7704 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档