动态规划
- 记忆型递归:在递归实现中用空间存储中间的计算结果,如果已经存在中间结果就直接取出使用。
- 递归转成递推:递归符合自然直觉从上层不断化简成相似子问题。递推从最底层开始不断推得问题的解。
- 空间优化:用最少的空间保存中间结果。(可以覆盖掉不需要的中间结果)。例:三角最大路径中可以把存储结果的二维数组优化成一位数组。甚至可以在优化用存放原始数据的地方来存储中间结果。
- 例题1最长上升子序列:考虑以每个字符为结尾的最长序列
- 例题2最长公共子序列:考虑两个串第i,j个字符相同,不同情况下的解(分类)
- 5-3例题3最佳加法表达式:思考把最右边的加号放在第i个数字右侧后,其余m-1个加号和数字形式的递归。可用记忆型递归实现。
- 解题思路:先用递归理出分解思路;通过控制答案的变量来设计状态,得到递推式;一般有几个状态就要用几维数组来存储中间结果;实现记忆型递归动规程序;思考递推的边界和顺序,实现递推程序;能否用滚动数组或者其他方式来优化空间
- helpJimmy:记忆型递归,计算每块板子left和right时间,并存在相应数组
- 滑雪:人人为我递推,按照从低到高的顺序依次递推出长度
- 神奇口袋和0-1背包:分类取和不取两种情况,写出递推式。按顺序递推结果,且根据递推的影响能够优化空间(0-1背包从右向左递推可以优化成一维空间)
- 6-3分蛋糕:最优解–>第一刀横切还是竖切的最小值–>第一刀切i的最小值–>其余刀怎么切得最优解:遍历的所有的切法。用记忆型递归实现。
总结:动规和递归的最大区别就是:用额外的空间来存储中间计算结果,避免递归程序的重复计算。甚至可以简单的把一个递归改写成记忆型递归的动规程序。当然,在理顺递推式之后可以自边界向上完成更高效的递推程序(减少函数栈)。更重要的是如何优化这额外的存储空间,用滚动数组和改变递推顺序等方法可以降成一维数组甚至单个变量
- 例题:
- 5-1拦截导弹:最长上升子序列思想,以每个数为结尾的状态来思考
- 5-2Zipper:以两个串的长度i,j为状态,[i][j]由[i-1][j]和[i][j-1]推得
- 6-1复杂整数划分:背包变形,(1)划分成k个数,要多加一个状态k来控制(2)非重复划分,01背包(3)奇数划分,可重复,当取j时要判断j是奇数且i>=j
- 6-2charm bracelet:01背包,可以优化空间