动态规划 第0讲:基础入门课

参考博文:
1、经典中的经典算法:动态规划(详细解释,从入门到实践,逐步讲解) 作者:BS有前途
2、告别动态规划,连刷40道动规算法题,我总结了动规的套路(微信公众号:帅地玩编程)
3、LeetCode:120 三角形最小路径和 动态规划解法 O(n)空间 作者:AkagiSenpai

一、动态规划的定义:

维基百科:
动态规划(Dynamic Programming, DP)在查找有很多重叠子问题的情况的最优解时有效。它将问题重新组合成子问题。为了避免多次解决这些子问题,它们的结果都逐渐被计算并被保存,从简单的问题直到整个问题都被解决。因此,动态规划保存递归时的结果,因而不会在解决同样的问题时花费时间。
动态规划只能应用于有最优子结构的问题。最优子结构的意思是局部最优解能决定全局最优解(对有些问题这个要求并不能完全满足,故有时需要引入一定的近似)。

动态规划算法是通过拆分问题定义问题状态和状态之间的关系,使得问题能够以递推的方式去解决。
动态规划算法的基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。

二、基本思想与解题策略:

动态规划,无非就是利用历史记录,来避免我们的重复计算。而这些历史记录,我们得需要一些变量来保存,一般是用一维数组或者二维数组来保存。
1、首先是拆分问题,就是根据问题的可能性,把问题划分成一步一步。这样就可以通过递推或者递归来实现。
关键就是这个步骤,动态规划有一类问题就是从后往前推。有时候我们很容易知道:如果只有一种情况时,最佳的选择应该怎么做。然后根据这个最佳选择往前一步推导,得到前一步的最佳选择。
2、找出数组元素之间的关系式,我觉得动态规划,还是有一点类似于我们高中学习时的归纳法的,当我们要计算 dp[n] 时,是可以利用 dp[n-1],dp[n-2],…,dp[1],来推出 dp[n] 的,也就是可以利用历史数据来推出新的元素值,所以我们要找出数组元素之间的关系式,例如 dp[n] = dp[n-1] + dp[n-2],这个就是他们的关系式了。而这一步,也是最难的一步,后面我会讲几种类型的题来说。
3、为减少重复计算,对每一个子问题只解一次(重点)将其不同阶段的不同状态保存在一个二维数组中。比如我们找到最优解,我们一个先将最优解保存下来,为了往前推导时能够使用前一步的最优解,在这个过程中难免有一些相比于最优解差的解,此时我们应该放弃,只保存最优解,这样我们每一次都把最优解保存了下来,大大降低了时间复杂度。

三、详细代码分析、推导、改进

话不多说,咱们来看一道经典例题(Leetcode 120.Triangle)

Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.

For example, given the following triangle

[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]
The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).

Note:

Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/triangle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这道题是找最小和,只能从左下角和右下角加上去。
但是,下面因为借鉴了一篇博文,为了少写一下,我就搬运他的部分内容过来了。他是最大值,性质是一样的,并不影响对动态规划的理解。

下面我们开始来分析了,

代码 Vision-1:

注:这个版本的代码是最初版本的代码,之所以放上来,是为了方便理解动态规划。如果放到Leetcode,是超时的。
可以看出每走第n行第m列时有两种后续:向下(i+1,j)或者向右下(i+1,j+1)
最后一行可以当做边界条件,所以我们自然而然想到递归求解。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值