动态规划求解 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 戳气球

相关推荐
记忆多2 小时前
c++内联函数
算法
仟濹2 小时前
【算法打卡day20(2026-03-12 周四)算法/技巧:哈希表,双指针,字符串交换处理】5个题
数据结构·算法·散列表
陌夏2 小时前
双指针与滑动窗口
算法
MicroTech20252 小时前
MLGO微算法科技,推出革命性量子算法ANQITE,推动量子计算新时代
科技·算法·量子计算
样例过了就是过了2 小时前
LeetCode热题100 子集
数据结构·c++·算法·leetcode·dfs
I_LPL3 小时前
day52 代码随想录算法训练营 图论专题5
java·算法·图论·并查集
jing-ya3 小时前
day 49 图论part1
算法·深度优先·图论
想吃火锅10053 小时前
【leetcode】98.验证二叉搜索树
算法·leetcode·职场和发展
一叶落4383 小时前
【LeetCode 172】阶乘后的零(C语言详解 | 数学规律 + 对数时间复杂度)
c语言·数据结构·算法·leetcode·动态规划