前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >「动态规划后篇」:考量适用指标

「动态规划后篇」:考量适用指标

作者头像
double
发布2018-04-02 17:31:45
6940
发布2018-04-02 17:31:45
举报
文章被收录于专栏:算法channel

主要推送关于对算法的思考以及应用的消息。培养思维能力,注重过程,挖掘背后的原理,刨根问底。本着严谨和准确的态度,目标是撰写实用和启发性的文章,欢迎您的关注。

01

你会学到什么?

前三天的推送都是关于动态规划算法的,先通过一个《装水最多的容器》初步感受了动态规划是怎么一回事,相比于直观的枚举算法,它能使求解更快地收敛;之后,推送了求解有效括号对的最大数,在求解过程中,根据两种情况分别建立了递推公式;接着解决了动态规划常常需要一个O(n)或更大的空间以及这样做得到个回报,即效率上的提升,并通过一个典型的爬楼梯的实际例子进一步验证了空间确实能够换取时间。

经过以上三天对动态规划的初步研究后,今天我们将要解决的问题只有一个,也是最为核心的问题,那就是什么样的问题适合用动态规划?

我想这也是大家一定想知道的。

02

核心问题

动态规划是好,但是我怎么就能知道我这个问题就能用动态规划来求解呢?

我们还得从面对的这个实际问题具有的特征入手吧,如果它符合动态规划的主要条件,那么就可以尝试用动态规划。

一般地,动态规划需要求解的问题具有2个核心特征:

  1. optimal-substructure property,最优化的子结构属性
  2. overlapping subproblems,重叠的子问题集

下面,解释什么是最优化的子结构属性。如果一个问题的最优解包含在一系列的子问题集的最优解,那么它就称为具有最优化的子结构属性。

还是拿爬楼梯的例子,如果想求解爬到第 i 层楼梯的所有方法,不就是相当于以下这个子问题 (subproblem) 吗:

求爬到第 i-1层的所有方法,和爬到第 i-2层的所有方法,两者的累计和,然后爬到第 i-1层的所有方法。

那么爬到第 i-1 层的所有方法,不又是一个子问题吗,相对于爬到第 i 层的方法不就叫 subsubproblem 吗!

这个爬楼梯问题是非常明显地具有最优化的子结构属性。

再来看下重叠的子问题是怎么定义的,下面是算法导论上解释

When a recursive algorithm revisits the same problem repeatedly, we say that the optimization problem has overlapping subproblems.

意思是说,当一个递归算法再次访问同一个问题时,这种事会出现一遍又一遍的,我们说这个最优化问题有重叠的子问题集。

这个有点抽象,我试着解释下,还是爬楼梯,如果我们分别求出了爬到第 i-1、第 i-2 层的所有方法,那么在求解爬到第 i 层的所有方法时,我们还得去解决爬到第 i-1、第 i-2 层的所有方法,这就是重叠的子问题。

当然,动态规划算法此时不会如此的傻,它会开辟一段内存,记录下爬到第 i-1、第 i-2 层的所有方法,然后在用到的时候直接 look up 了,这也是昨天提到的用空间换取时间的方法。

好了,以上便是两个动态规划问题常常具备的特征,一般地,我们待解决的问题满足了这两个特征,就值得试一试动态规划。

下面再看一个应用动态规划求解longest common subsequence (LCS) 的例子。

03

LCS

LCS的概念

给定两个字符串 x 和 y, 它们的最长子序列具有的长度。 这个概念容易让人误解,以为最长的子字符串必须是相邻的。其实是不必的! 例如 X = "ABCBDAB" , Y = "BDCABA",则 最长子序列长度为4,为 B C A B

例子分析

为什么可以用动态规划来求解? 看看满足那两个特征吗。第一,是最优化的子问题吗? 是!

以下分析是LCS最重要的部分

如果字符串 Xm 和 字符串 Yn 的 X.charAt(m) 和 Y.charAt(n) 相等,那么最长子字符串一定等于字符串 Xm-1 和 字符串 Yn-1 的最长子字符串再加上这个相等字符。

如果字符串 Xm 和 字符串 Yn 的X.charAt(m) 和 Y.charAt(n)不相等,那么最长子字符串一定等于以下两者的较大者:

  1. 字符串 Xm-1 和 字符串 Yn 的最长子字符串。
  2. 字符串 Xm 和 字符串 Yn-1 的最长子字符串。

根据上面的分析,子问题具有最优化的子结构属性,并且容易看出也具备重叠的子问题集,因为求Xm和Yn的最长子字符串要用到Xm-1或 Yn-1的中的至少一个。

上面的分析,实际上得出了一个递推公式,具体的体现在下面的代码中。

04

LCS 代码实现

//返回x和y的最长子串 public static int lcs(String x, String y){ return lcf(x,y,x.length()-1,y.length()-1); } //i : x索引 private static int lcs(String x, String y, int i, int j){ //递归返回的条件 if(i==-1 || j==-1) return 0; //如果相等 if(x.charAt(i)==y.charAt(j)){ return lcf(x,y,i-1,j-1)+1; } //如果不等,返回较大者 return Math.max(lcf(x,y,i-1,j), lcf(x,y,i,j-1)); }

算法的时间复杂度为 O(x.length()+y.length()),空间复杂度为函数的入栈空间。

05

总结

回答了适合动态规划求解的问题主要考量的2个指标,满足了这两个指标后,便能找出递推公式,最后不要忘了递归返回的条件。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-11-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员郭震zhenguo 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档