DP问题总结

对DP问题的类型做一个总结,以leetcode上的题目为例:

1.简单的递归,例如斐波拉契的序列进行递归

(1) 第一种是比较简单的, 直接地按照上面步骤就可以解出来的, 确定递归量, 然后按递归式迭代就可以得到。 这种类型的题目是: Climbing Stairs,Decode Ways和Unique Binary Search Trees。

Climbing Stairs中递推量很清晰, 就是爬到i级楼梯有多少种可行爬法。 而对于递推式我们可以看出, 要到达i级楼梯, 必须通过i-1级或者i-2级(以为只能爬一级或者两级), 如此可以得到到达i级楼梯的方式有f(i)=f(i-1)+f(i-2)种, 这样递推式也就出来了。 而初始条件则是一级楼梯是一种解法, 两级楼梯是两种解法(2或者11)。 有了这些接下来递推到n级楼梯返回即可, 空间复杂度是O(n)(一维动态规划乘以每一步的常量操作)。 空间上我们发现每一步,只需要前两步的历史信息, 所以我们不需要存储所有历史信息, 只需要保存前两步, 然后迭代替换就可以了, 所以空间复杂度是O(2)=O(1), 这里对应于上面的第四步。

2.全局解和局部解的问题

虽然也是一维动态规划, 但是区别在于这类题目需要维护两个递推量, 所以思路上有一点技巧。 不过还是比较有通法的, 我通常把这种方法称为”局部最优和全局最优解法“。 这种方法中我们通常维护两个量, 一个是到目前为止最好的结果信息(全局最优), 另一个必须包含新加进来的元素的最好的结果信息(局部最优), 然后还是推导递推式, 计算初始条件, 跟动态规划的通常思路一样了。 Maximum Subarray和Best Time to Buy and Sell Stock就是这种类型的题目。

Maximum Subarray中对于递推量我们维护两个,一个是到目前为止最好的子数组, 而另一个量则是加入当前元素之后, 包含当前元素的最好的子数组, 最终我们是看全局最优的变量的最优值, 而局部最优却是我们在递推过程中维护全局最优所需要的。

递推式还是有点技巧, 第i+1步表达式如下:
local[i+1]=Math.max(A[i], local[i]+A[i]),就是局部最优是一定要包含当前元素,所以不然就是上 一步的局部最优local[i]+当前元素A[i](因为local[i]一定包含第i个元素,所以不违反条件),但是如果local[i]是负的,那么加上他就不如不需要的,所以不然就是直接用A[i];

global[i+1]=Math(local[i+1],global[i]),有了当前一步的局部最优,那么全局最优就是当前的局部最优或者还是原来的全局最优(所有情况都会被涵盖进来,因为最优的解如果不包含当前元素,那么前面会被维护在全局最优里面,如果包含当前元素,那么就是这个局部最优)。

初始条件都是0或者第一个元素既可以了, 一遍扫过来, 每次迭代更新两个量(都是常量时间), 所以时间是O(n)。 空间上可以看出只需要上一步的信息, 所以只需要保存上一步的全局最优和局部最优即可, 复杂度是O(2) = O(1)。

3.背包问题

背包的重量是确定的,可以拿n件物品,求最后拿的物品的价值是多大。
这一类问题的功能点,是有一个限制条件显示不能都拿,是如何选的问题,最后有一个最优问题,就是价格最优。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值