什么是动态规划
20世纪50年代初美国数学家R.E.Bellman等人在研究多阶段决策过程(multistep decision process)的优化问题时,提出了著名的最优化原理(principle of optimality),把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解,创立了解决这类过程优化问题的新方法——动态规划。
道理都懂, 但做题总感觉差点什么
接下来我会取3个leetcode的动态规划题来举例, 读者最好先试着做做哦.
它们分别是
(go代码算法可参看我的github)
不知道思路的话, 试一试以下三个步骤.
先弄清楚解的依赖关系
比如221题, 某个点的解由上,左,左上3个点决定, 764题, 点的解由上,下,左,右4个点决定.
如何找依赖关系呢? 我的方法是将例子写在本子上, 人脑去验算, 尝试找到每个解之间的关系, 当然多做两个题之后也就孰能生巧了.
思考过程也是有套路的:
- 弄清楚在每一步求解过程中有那些
变量
控制解
- 如211题, 对于每一个i行j列都有一个解去对应, 变量就是i行j列, 764题同样.
- 再说322题, 题目中硬币是无限的, 在求每一步的解时, 硬币没有发生任何变化, 那么影响解的变量只有amount.
- 让
变量
依次改变(一般是从小变大), 去演算解, 如在求斐波那契数列第10项时, 先去演算第一项, 再去演算第二项, 你就会发现两项之间的关系.
- 如211题,
p[i,j]
和p[i-1,j-1]
之间的关系就是: 至少p[i-1,j-1]
是正方形,p[i,j]
才能是正方形,
再思考p[i,j]
和p[i,j-1]
的关系也是同理, 现在你就得到了解之间的关系. - 如322题,
p[amount]
和p[amount-1]
的关系就是: 如果我取出了面值为1的硬币, 那么所需硬币的最小数量p[amount]
=1(取走了1个硬币)+p[amount-1(硬币面额为1)]
,
再推理一下, 这里的1
其实是硬币的面额, 替换下变量既得到p[amount] = 1 + p[amount - coins[i]]
最后将思考结果用公式写出来, 方便写代码.
公式可以看做黑盒的方法, 可不用管题目参数, 直接写变量和解之间的公式.
如
- 211题
p[i,j] = min(1 + p[i-1,j], 1 + p[i,j-1], 1 + p[i-1,j-1])
- 764题
p[i,j] = min(1 + p[i-1,j], 1 + p[i+1,j], 1 + p[i,j-1], 1 + p[i,j+1])
- 322题
p[amount] = min(1 + p[amount - coins[i]], i=0~len(coins))
ps: 如果不能理解, 就在参考看看每个题的注释: 211, 764, 322.
想好如何保存解
弄清楚解的依赖关系之后, 还需要弄清楚如何将上一步的解保存下来提供给下一步利用.
注意这里的保存
是一个广泛的意思, 不一定是存在一个全局的数据结构里(如数组), 也可以存在局部变量中.
特别是做大量数据的题时候, 尽量用局部变量去存储这一步的解, 实在没办法再想到用全局去存.
举个例子: 求斐波那契数列的第10项
这个题有两种解法,
- 声明一个数组
s [10]int
, 循环10次,s[i] = s[i-1] + s[i-2]
- 声明两个变量
a,b
, 循环10次,c=a+b; a=c
可以看到解法1所需要的空间比2大得多, 当题目没要求需要得到每一步的解的时候, 最好使用解法2.
当然两种解法的差别还不只是空间.
如764题, 每个点的解由上,下,左,右4个点决定, 那么如果要将解存到全局的话, 需要声明一个复杂的数据结构以保存4个解, 最后写出来又复杂, 所需要空间也大.
所以更好的方式是在遍历过程中, 直接用局部变量保存上一步的解, 具体做法看代码啦.
循环(遍历)
最后 循环也很关键, 它直接影响了结果的正确性 和 保存解的复杂度.
对于每一个题, 解的公式不一样, 所以遍历的先后顺序也不一样.
但其实只需要记得保持一个原则: 按照依赖关系去遍历, 保证上一步解在本次操作之前已经正确的解出来了.
所以要将解的依赖关系理解透彻.
在写代码的过程中, 记得反复推敲此行代码所依赖的上一步解是否已经解过了
(笔者也才开始做leetcode, 没啥心得, 不能落笔于此, 惭愧. 先题海战术吧~)
具体做法就看我的github吧. 211题, 764题, 322题
参考
ps: 学习的第一步一定是仿照(抄袭), 写不出代码就先把别人的代码抄懂, 这很正常. 不过之后记得多总结, 思考别人是怎么想到答案的, 最后尝试用学到的几种不同的思维方式去解题.
ps: 做题真费脑子, 希望自己能坚持, 等到变强了, 做题也就轻松了.
网友评论