动态规划解题思路

一直以来,对动态规划的理解处于一个模糊的状态,就是一种似乎懂但遇到问题未必能行的状态……

然后,最近重点在leetcode上找了一些动态规划的题目做了一下,逐渐有了一些思路。

 

我觉得leetcode上对动态规划思想的概括非常到位,所以记录在这里

动态规划(英语:Dynamic programming,简称 DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。

动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。

动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再根据子问题的解以得出原问题的解。动态规划往往用于优化递归问题,例如斐波那契数列,如果运用递归的方式来求解会重复计算很多相同的子问题,利用动态规划的思想可以减少计算量。

通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,具有天然剪枝的功能,从而减少计算量:一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。

链接:https://leetcode-cn.com/tag/dynamic-programming/
来源:力扣(LeetCode)

算法课上老师也讲到过:

(1)动态规划和分治是非常像的,都是要把大问题分解成子问题,然后将子问题的解进行合并起来求原问题的解。

(2)动态规划和分治的区别就是,分治的子问题之间一般不重复,动态规划的子问题会有重复,而要把所有的子问题都列出来会是一个非常复杂的问题。而在计算过程中通过记录已经计算过的子问题的解,避免重复计算,这就是动态规划进行剪枝的特点。

(3)动态规划问题一般可以找到最优子结构(子问题)和递归子方程,通过这两个条件,就可以得出动态规划问题的解了。(递归子方程可以通过递归实现,也可以用迭代实现)

知乎上的这个回答也挺好:如何理解动态规划? - 牛岱的回答 - 知乎 https://www.zhihu.com/question/39948290/answer/612439961

 

那么,解动态规划问题的一般方法是怎样呢?

以前,我是想直接找到最优子结构,然后去找递归子方程。后来我觉得这种方法不合理,起码是反常识的。

如果一开始我不知道这个问题是动态规划问题,怎么可以直接就去找最优子结构和递归方程呢?而且一些复杂的问题,很难直接找到最优子结构和递归方程。

在leetcode刷题的过程中,我发现大家解答的路径都是这样的:

(1)暴力法:先搞清楚问题想要得到的结果是什么,先要得到这个结果,最直观的方法是什么?

一般这个方法的时间复杂度会比较高,中间会有很多的重复计算,不过没关系,这个方案得出来,主要是将问题先解出来,后面再优化。

(2)动态规划:在使用暴力法的解题过程中,我们基本上就能知道问题最终要求的是什么,和要求得这个结果的所有子问题是什么。

此时,我们可以去找子问题之间是否存在重复计算,而这种重复计算是否存在一种递归关系,比如斐波那契数列的f(i) + f(i+1) = f(i+2)。得到了递归方程,基本上这个问题就可以解出来了。

一般来说,一个问题要转化成数学问题/程序,需要有一个合理的解释,而有些问题比较复杂的时候,可以对其进行简化或者加限定条件。比如给一个长度为n的数组,n太多了难以解决,可以先考虑一个,然后两个;或者把它分成左右两半,看左半部分会不会做,右半部分会不会做。

再比如https://leetcode-cn.com/problems/wildcard-matching/这个题,这个题需要判断s和p是否匹配,一般两个字符串的匹配可以通过同时遍历比对即可,但是这个题有通配符,尤其是*,使问题变得复杂。这时候,我们想到可以看单个字符是否匹配的方法,这很简单,两边各取一个字符比对即可。但是,问题来了,需要将s和p中的每个字符互相比对吗?扩展成2个字符的时候怎么也是要所有2个可能的字符吗?在子问题的选择上遇到了问题。这时可以回看一下问题,问题其实是判断s的全部和p的全部是否匹配,我们在找子问题的时候不一定要找s的所有子字符串和p的所有子字符串,其实限定都是以s的结尾为结尾的子字符串和以p的结尾为结尾的子字符串进行比较,首先比对尾部,一点点扩展到索引为0的位置,就比较完了整个s和p字符串,也就得到了结果。加了一个一端固定的限定条件,就使思路瞬间清晰。

实例,绞尽脑汁做出的方案,有时候需要注意一些细节点,比如二叉搜索树的特点。。。https://leetcode-cn.com/problems/unique-binary-search-trees-ii/solution/dong-tai-gui-hua-si-kao-guo-cheng-by-flushmeteor-2/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值