刷题总结——动态规划

总论

怎么求解?

  • 回溯
  • 记忆化搜索
  • 递推(方便进行空间复杂度优化)

求什么?

  • 方案数
  • 最大值
  • 最小值

状态方程

对应关系:

  • 转移状态的定义(回溯入口)
  • 边界条件(边界状态如何递推得到其实状态,回溯的终止条件)
  • 如果递推公式是求最小,边界初始化成INT_MAX_ * 如果递推公式求最大,边界为0或1
  • 如果是乘法,需要处理负数正数两种状态
  • 取一个特例: 从单个元素角度看一下
空间复杂度优化
  • O(mn)->O(n) 滚动数组,注意方向
  • O(mn)->O(1) 单个变量记录状态

分类

分类 递推公式 边界条件 备注
爬楼梯(方案数) dp(i) = dp(i-1) + dp(i-2) 起始位置f(0), f(1), f(2) O(n), 加法原理+取余
打家劫舍(选与不选) dp(i) = max(dp(i-1), + dp(i-2)+value[i-1]) 起始位置 O(n), 选与不选
最大子数组和(选与不选) dp(i) = max(nums(i), dp(i-1)+nums(i-1)); 无需处理 Kadane算法,还有前缀和做法(滑动窗口找当前前缀和减当前最小前缀和)
网格dp dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + frame[i-1][j-1]; 起始位置+最左和最上的边界 O(n)(m),通常是2D网格,注意空间优化
0-1背包(选与不选) dp[i] = max(dp[i-1][c], dp[i-1][c-w[i]]+v[i]) 起始位置与默认值 O(n)(value), 空间复杂度优化
完全背包(选与不选) dp[i] = max(dp[i-1][c], dp[i][c-w[i]]+v[i]) 起始位置与默认值 O(n)(value), 空间复杂度优化
多重/分组背包(选几次) dp[i] = \sum{dp[i-1][j-v*i]} for i=1..k 起始位置dp(0)(0)=1默认值0 O(n)(value),同一物品可选k次,空间复杂度与其他背包一样,多重背包k在外面,分组k在里面
线性序列dp (LCS, LIS问题,2个字符串s1(:i), s2(:j)的关系) dp[i][j] = max(dp[i-1][j], dp[i][j-1]); 边界条件多1行1列,初始值受问题影响 O(m)(n), 一般是在数组前缀和后缀上转移的,空间复杂度优化
状态机dp f[i][j]为第i天在j状态下,需要与i-1天建立联系,如股票买卖 边界条件,可能为-∞ O(n), 画状态图,适合dfs
划分型dp
区间dp dp[i][j]=dp[i+1]dp[j-1]+2;``dp[i][j]=max(dp[i+1][j], dp[i][j-1]) 边界条件主要是允许区间越界的地方如何表示(上三角矩阵),和循环变量增长的方向。 O(m)(n), 从小区间转移到大区间

最长递增子序列LIS问题的优化

  • 从O(n2)到O(n),思路:交换状态与状态值
    • O(n2): 状态是以i为结尾元素的LIS的长度
    • O(n): 状态是长度为i+1的序列里面构成的上升子序列结尾元素最小值(最小值,才有机会扩展序列)贪心+二分
      注意此时记录的额外空间g(n)不是子序列

带特殊数据结构的DP

  • 前缀和优化
  • 单调栈优化
  • 单调队列优化
  • 树状数组优化

参考资料

  1. https://leetcode.cn/circle/discuss/tXLS3i/
posted @ 2024-11-06 22:29  haydenhs  阅读(44)  评论(0)    收藏  举报