动态规划求解 20 个通用模板

目标是做到:

看到题 → 直接匹配模板 → 改几行代码就能做

难度和面试频率排序。


一、线性 DP(最基础)

模板 1:爬楼梯型

最基础 DP。

特征:

  • 每一步依赖前 1~2 个状态
python 复制代码
dp = [0] * (n+1)

dp[0] = 1
dp[1] = 1

for i in range(2, n+1):
    dp[i] = dp[i-1] + dp[i-2]

return dp[n]

典型题:

  • 爬楼梯
  • 斐波那契
  • 青蛙跳台阶

二、最大 / 最小值 DP

模板 2:最大子数组和

特征:

  • 连续
  • 以当前位置结尾
python 复制代码
dp[0] = nums[0]

for i in range(1, n):
    dp[i] = max(nums[i], dp[i-1] + nums[i])

return max(dp)

经典题:

  • 最大子数组和

三、打家劫舍模板

模板 3:选 / 不选

python 复制代码
dp[0] = nums[0]
dp[1] = max(nums[0], nums[1])

for i in range(2, n):
    dp[i] = max(
        dp[i-1],
        dp[i-2] + nums[i]
    )

经典题:

  • 打家劫舍
  • 股票简化版

四、背包 DP 模板


模板 4:0-1 背包

python 复制代码
for i in range(n):
    for j in range(W, weight[i]-1, -1):

        dp[j] = max(
            dp[j],
            dp[j-weight[i]] + value[i]
        )

特点:

  • 倒序遍历

经典题:

  • 分割等和子集
  • 目标和

模板 5:完全背包

python 复制代码
for i in range(n):
    for j in range(weight[i], W+1):

        dp[j] = max(
            dp[j],
            dp[j-weight[i]] + value[i]
        )

特点:

  • 正序遍历

经典题:

  • 零钱兑换
  • 完全平方数

模板 6:背包求组合数

python 复制代码
dp[0] = 1

for coin in coins:
    for j in range(coin, amount+1):

        dp[j] += dp[j-coin]

经典题:

  • 零钱兑换 II

五、子序列 DP


模板 7:最长递增子序列(O(n²))

python 复制代码
dp = [1] * n

for i in range(n):
    for j in range(i):

        if nums[j] < nums[i]:
            dp[i] = max(dp[i], dp[j] + 1)

return max(dp)

模板 8:最长公共子序列

python 复制代码
for i in range(1, m+1):
    for j in range(1, n+1):

        if s1[i-1] == s2[j-1]:
            dp[i][j] = dp[i-1][j-1] + 1

        else:
            dp[i][j] = max(
                dp[i-1][j],
                dp[i][j-1]
            )

模板 9:最长回文子序列

python 复制代码
for i in reversed(range(n)):
    for j in range(i+1, n):

        if s[i] == s[j]:
            dp[i][j] = dp[i+1][j-1] + 2
        else:
            dp[i][j] = max(
                dp[i+1][j],
                dp[i][j-1]
            )

六、字符串编辑 DP


模板 10:编辑距离

python 复制代码
for i in range(1, m+1):
    for j in range(1, n+1):

        if word1[i-1] == word2[j-1]:
            dp[i][j] = dp[i-1][j-1]

        else:
            dp[i][j] = 1 + min(
                dp[i-1][j],
                dp[i][j-1],
                dp[i-1][j-1]
            )

七、网格 DP


模板 11:路径数量

python 复制代码
for i in range(m):
    for j in range(n):

        dp[i][j] = dp[i-1][j] + dp[i][j-1]

模板 12:最小路径和

python 复制代码
for i in range(m):
    for j in range(n):

        dp[i][j] = min(
            dp[i-1][j],
            dp[i][j-1]
        ) + grid[i][j]

八、状态机 DP


模板 13:股票问题

python 复制代码
for i in range(1, n):

    dp[i][0] = max(
        dp[i-1][0],
        dp[i-1][1] + price
    )

    dp[i][1] = max(
        dp[i-1][1],
        dp[i-1][0] - price
    )

九、区间 DP


模板 14:区间合并

python 复制代码
for length in range(2, n+1):

    for i in range(n-length+1):

        j = i + length - 1

        for k in range(i, j):

            dp[i][j] = min(
                dp[i][j],
                dp[i][k] + dp[k+1][j]
            )

经典题:

  • 戳气球
  • 合并石头

十、DP + 位运算(进阶)


模板 15:状态压缩 DP

python 复制代码
for mask in range(1<<n):

    for i in range(n):

        if mask & (1<<i):

            dp[mask] = min(
                dp[mask],
                dp[mask^(1<<i)] + cost
            )

经典题:

  • TSP
  • 最短 Hamilton 路

十一、DP + 树


模板 16:树形 DP

python 复制代码
def dfs(node):

    for child in node.children:

        dfs(child)

    dp[node] = combine(children)

经典题:

  • 树上打家劫舍

十二、DP + 前缀


模板 17:分割 DP

python 复制代码
for i in range(1, n+1):

    for j in range(i):

        dp[i] = min(
            dp[i],
            dp[j] + cost(j, i)
        )

经典题:

  • 单词拆分
  • 回文分割

十三、DP + 数学


模板 18:Catalan 数

python 复制代码
for i in range(2, n+1):

    for j in range(i):

        dp[i] += dp[j] * dp[i-1-j]

经典题:

  • 不同二叉搜索树

十四、DP + 双序列


模板 19:最长公共子串(连续)

python 复制代码
if s1[i] == s2[j]:
    dp[i][j] = dp[i-1][j-1] + 1
else:
    dp[i][j] = 0

十五、DP + 环


模板 20:环形 DP

python 复制代码
# 拆成两个线性问题

case1 = rob(nums[:-1])
case2 = rob(nums[1:])

return max(case1, case2)

经典题:

  • 打家劫舍 II

最重要的 DP 判断口诀

看到题先问 4 个问题

1️⃣ 连续吗?

  • 连续 → 子数组

2️⃣ 选不选?

  • 选 / 不选 → 背包

3️⃣ 两个字符串?

  • 字符串 DP

4️⃣ 区间操作?

  • 区间 DP

最推荐掌握的 10 个 DP(面试命中率最高)

1 爬楼梯

2 打家劫舍

3 最大子数组和

4 分割等和子集

5 零钱兑换

6 最长递增子序列

7 最长公共子序列

8 编辑距离

9 最小路径和

10 戳气球

相关推荐
澈2071 小时前
C++并查集:高效解决连通性问题
java·c++·算法
旖-旎2 小时前
深搜练习(单词搜索)(12)
c++·算法·深度优先·力扣
企客宝CRM3 小时前
2026年中小企业CRM选型指南:企客宝CRM处于什么位置?
android·算法·企业微信·rxjava·crm
橙淮3 小时前
二叉树核心概念与Java实现详解
数据结构·算法
米罗篮4 小时前
DSU并查集 & 拓展欧几里得-逆元
c++·经验分享·笔记·算法·青少年编程
橙淮4 小时前
双指针法:高效算法解题的利器
算法
初心未改HD4 小时前
深度学习之MLP与反向传播算法详解
人工智能·深度学习·算法
刀法如飞4 小时前
【Go 字符串查找的 20 种实现方式,用不同思路解决问题】
人工智能·算法·go
技术小黑6 小时前
CNN算法实战系列03 | DenseNet121算法实战与解析
pytorch·深度学习·算法·cnn