LeetCode-【总结】dp问题小结

dp分类

dp问题大致分为:

  • 线性dp
  • 背包dp
  • 序列dp
  • 区间dp
  • 状压dp
  • 数位dp
  • ……

背包dp

参见:自己的背包dp总结

序列dp

经典问题:最长上升子序列、最长公共子序列
参见:自己的LIS、LCS总结

一般时间复杂度 O(nlogn) 或 O(n^2)
例如,LCS中,dp[i][j] 一般定义为 两个序列或字符串中分别在第i、j个位置结尾的序列对应的 最长公共子序列长度
难一点的问题会涉及到 找出该最长公共子序列

区间dp

一般dp[i][j]表示一个序列中s[i]~s[j]这个区间的答案数,然后由dp[i][j]转移到dp[i+1][j]、dp[i][j+1]等,明显地,i、j代表开/闭区间的两个端点
经典问题:最长回文子串问题
参见:回文串题解推荐
一般在写代码时,第一层循环为len = j - i + 1;第二层循环为起点i

状压dp

dp[i][state],其中state是二进制表示的一种状态,题目一般状态数量有限,可以二进制枚举表示
dp数组索引一般是状态state(二进制表示)
经典例题:状压dp例题题解

数位dp

此类题目一般和数字有关,且数字取值范围特别大,但位数有限,比如10*9只有10位,可以利用数位作为dp的维度而非数值大小
比如需要枚举0~4321有几个数,对于最高位4可以枚举0 ~ 3的情况(0000 ~ 3999),对于次高位3可以枚举0 ~ 2的情况(4000 ~ 4299),以此类推,共计4000+300+20+1+1 = 4322个,答案即4322
经典例题:数位dp例题题解

小结

其实,上述dp分类只是对于特定dp问题提出普适性dp状态数组定义、转移方式。
其实写了这么多dp最难的还是状态定义 T_T,既要考虑转移还要考虑时间复杂度(这个题目数据一般会提示,比如数据范围只有 10 ^ 3大概率用 O(n^2) 的算法)

题量还不够,继续努力哇!虎年冲冲冲!!!

你可能感兴趣的:(leetcode,动态规划,算法)