动态规划专题 🎯
动态规划是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决。
动态规划(Dynamic Programming,简称DP)是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题。
🎯 动态规划核心思想
动态规划的核心思想是:将复杂问题分解为更简单的子问题,通过解决子问题来解决原问题。
动态规划的特征
- 重叠子问题:子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到
- 最优子结构:大问题的最优解可以由小问题的最优解推出
- 无后效性:某阶段状态一旦确定,就不受这个状态以后决策的影响
动态规划解题步骤
- 确定dp数组(dp table)以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 举例推导dp数组
📚 学习内容
理论基础与总结
基础动态规划
从最简单的动态规划问题开始,建立动态规划的思维模式:
- 斐波那契数 - 最经典的动态规划入门题
- 爬楼梯 - 理解状态转移方程的建立
- 使用最小花费爬楼梯 - 最小代价路径问题
- 不同路径 - 二维动态规划入门
- 不同路径II - 带障碍物的路径问题
- 整数拆分 - 数学问题中的动态规划
- 不同的二叉搜索树 - 卡特兰数的动态规划解法
背包问题
背包问题是动态规划的经典应用,也是很多复杂问题的基础:
01背包
- 01背包理论基础 - 01背包的核心思想和实现
- 01背包理论基础二 - 01背包的空间优化
- 分割等和子集 - 01背包的变形应用
- 最后一块石头的重量 - 转化为01背包问题
- 目标和 - 正负号问题转化为背包
- 一和零 - 二维费用的01背包
完全背包
- 完全背包理论基础 - 完全背包的基本思想
- 零钱兑换II - 求组合数的完全背包
- 组合总和IV - 求排列数的完全背包
- 爬楼梯完全背包版本 - 用完全背包思想解决爬楼梯
- 零钱兑换 - 求最少硬币数的完全背包
- 完全平方数 - 完全平方数分解问题
- 单词拆分 - 字符串问题中的完全背包思想
其他背包
打家劫舍系列
经典的动态规划问题系列,涉及不同的约束条件:
股票问题
股票买卖问题的系列解法,状态机的经典应用:
- 买卖股票最佳时机 - 只能买卖一次的简单情况
- 买卖股票最佳时机II - 可以多次买卖的贪心与DP解法
- 买卖股票的最佳时机III - 最多完成两笔交易
- 买卖股票的最佳时机IV - 最多完成k笔交易
- 最佳买卖股票时机含冷冻期 - 有冷冻期的股票交易
- 买卖股票的最佳时机含手续费 - 有手续费的股票交易
- 股票问题总结 - 股票问题的总结和状态设计技巧
子序列问题
涉及序列处理的动态规划问题:
- 最长递增子序列 - 经典的LIS问题
- 最长连续递增序列 - 连续性约束的子序列
- 最长重复子数组 - 两个数组的公共子数组
- 最长公共子序列 - 经典的LCS问题
- 不相交的线 - LCS问题的变形
- 最大子序和 - 连续子数组的最大和
编辑距离
字符串编辑问题的动态规划解法:
- 判断子序列 - 子序列判断的简单问题
- 不同的子序列 - 计算子序列个数
- 两个字符串的删除操作 - 使两字符串相同的最少删除次数
- 编辑距离 - 经典的字符串编辑距离问题
- 编辑距离总结 - 编辑距离问题的总结和扩展
回文问题
涉及回文字符串的动态规划问题:
💡 动态规划的特点
优点
- 最优性:能够保证找到最优解
- 通用性:适用于很多优化问题
- 系统性:有明确的解题步骤和思路
缺点
- 空间复杂度:通常需要额外的存储空间
- 时间复杂度:可能存在冗余计算
- 理解难度:状态设计和转移方程需要深入思考
🎯 学习建议
- 掌握基本概念:深入理解重叠子问题、最优子结构等核心概念
- 熟练五步法:按照动态规划五步法系统地分析问题
- 多做经典题目:从简单的斐波那契开始,逐步提高难度
- 理解状态设计:学会如何合理地设计状态和状态转移
- 注意空间优化:在掌握基本解法后,学习如何优化空间复杂度
- 分类练习:按照背包、序列、树形DP等分类进行专项练习
记住:动态规划的关键在于正确的状态定义和状态转移方程的推导! 🚀