leetcode-动态规划三种问题的异同点

一、问题定义

|---------|-------------|---------------------------------|
| 问题 | 输入 | 输出 |
| 最长重复子数组 | 两个数组/字符串A,B | 最长的连续子数组,同时出现在A和B中 |
| 最长公共子序列 | 两个序列A,B | 最长的子序列(元素相对顺序一致,可不连续),同时出现在A和B中 |
| 编辑距离 | 两个字符串A,B | 将A转换成B所需的最少插入,删除,替换操作次数 |

二、动态规划解法对比

1.状态定义

  • 重复子数组:dpij表示以Ai-1和Bj-1结尾的最长公共子串的长度
  • 公共子序列:dpij表示A0..i-1和B0..j-1的最长公共子序列的长度
  • 编辑距离:dpij表示将A0..i-1 转换成 B0..j-1所需的最少操作次数

2.状态转移方程

设m= len(A),n = len(B),下标从1开始(即dpij 对应Ai-1与Bj-1

|-------|-------------------------------------|---------------------------------------------------------------------|
| 问题 | 当Ai-1==Bj-1 | 当Ai-1!=Bj-1 |
| 重复子数组 | dpij=dpi-1i-1+1 | dpij=0(连续中断) |
| 公共子序列 | dpij=dpi-1j-1+1 | dpij=max(dpi-1j,dpij-1) |
| 编辑距离 | dpij=dpi-1j-1(无需操作) | dpij=min(dpi-1j, dpij-1,dpi-1j-1)+1 |

3.初始化

  • 重复子数组:dp0j=0,dpi0=0(空串匹配长度为0)
  • 公共子序列:同上,全0
  • 编辑距离:dpi0=i (将A前i个字符删除),dp0j=j(插入j个字符)

4.最终答案

  • 重复子数组:max(dpij) ,即DP表中最大值(因为最佳子串不一定在末尾结束)
  • 公共子序列:dpmn
  • 编辑距离:dpmn

三、异同点

相同点

  1. 动态规划框架:都基于二维表,逐行逐列递推
  2. 时间复杂度:均为O(mn),空间均可优化到O(min(m,n))
  3. 子结构:都利用了"前缀"的最优解来构造更长前缀的最优解

不同点

维度 重复子数组 公共子序列 编辑距离
连续性要求 必须连续 不要求连续 不直接涉及连续,但通过操作调整
不等时的行为 置 0(重新开始) 取左/上的最大值(跳过) 取三种操作的最小值+1
初始化 全 0 全 0 第一行、第一列为 i, j
最终答案 全局最大值 右下角 右下角
DP 值的含义 以当前位置结尾的最长匹配长度 前缀的最长公共子序列长度 前缀的最小编辑代价
空间优化难度 简单(仅需上一行) 中等(需两行) 中等(需两行,并保存左上角)

四、举例说明

设 A = "abcde", B = "abfce"

1. 最长重复子数组(公共子串)

  • 匹配的连续段:"ab"(长度 2)、"c"(长度 1)、"e"(长度 1)。

  • DP 表(只写部分):

    text

    复制

    下载

    复制代码
         a  b  f  c  e
    a    1  0  0  0  0
    b    0  2  0  0  0
    c    0  0  0  1  0
    d    0  0  0  0  0
    e    0  0  0  0  1

    最大值 = 2 → "ab"

2. 最长公共子序列

  • 子序列:"abce"(长度 4)。

  • DP 表(右下角):

    text

    复制

    下载

    复制代码
         a  b  f  c  e
    a    1  1  1  1  1
    b    1  2  2  2  2
    c    1  2  2  3  3
    d    1  2  2  3  3
    e    1  2  2  3  4

    答案 = 4。

3. 编辑距离("abcde""abfce"

  • 最少操作:将 'c' 替换为 'f',然后删除 'd'?实际最优:把 'c' 改成 'f'(1 次),再把 'd' 删除(1 次),共 2 次。

  • DP 表右下角 = 2。

五、代码示例

1.最长重复子数组

python 复制代码
def findLength(A, B):
    m, n = len(A), len(B)
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    ans = 0
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if A[i-1] == B[j-1]:
                dp[i][j] = dp[i-1][j-1] + 1
                ans = max(ans, dp[i][j])
    return ans

2.最长公共子序列

python 复制代码
def longestCommonSubsequence(A, B):
    m, n = len(A), len(B)
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if A[i-1] == B[j-1]:
                dp[i][j] = dp[i-1][j-1] + 1
            else:
                dp[i][j] = max(dp[i-1][j], dp[i][j-1])
    return dp[m][n]

3.编辑距离

python 复制代码
def minDistance(A, B):
    m, n = len(A), len(B)
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    for i in range(1, m + 1):
        dp[i][0] = i
    for j in range(1, n + 1):
        dp[0][j] = j
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if A[i-1] == B[j-1]:
                dp[i][j] = dp[i-1][j-1]
            else:
                dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1
    return dp[m][n]
相关推荐
半夏微凉半夏殇1 小时前
x11与weston对比,优先选哪个
leetcode·均值算法·eclipse
2501_906565121 小时前
数学之美探究
算法
oier_Asad.Chen1 小时前
【洛谷题解/AcWing题解/OI学习笔记】洛谷P2868【USACO07DEC】Sightseeing Cows G(01分数规划求最大比率)
算法·图论·spfa·二分·负环
leisoo80973 小时前
财报数据怎么排雷本地化Python构建财务异常预警系统
人工智能·python·算法
luj_17685 小时前
塔防牌:策略与卡牌的智慧碰撞
服务器·c语言·开发语言·经验分享·算法
郝学胜-神的一滴6 小时前
干货版《算法导论》17:二叉树核心原理、遍历逻辑与高阶实操全解
数据结构·c++·python·算法·计算机·编程
爱编程的小新☆6 小时前
【LeetCode】从递归到 Flood Fill:5 道题吃透 DFS 的选择、回溯与标记
java·算法·leetcode·深度优先·回溯·flood fill
Water_Sunzhipeng6 小时前
2024牛客暑期多校训练营1
算法
hetao17338376 小时前
2026-08-09~08-14 hetao1733837 的刷题记录
c++·算法
技术小黑6 小时前
RNN算法实战系列06 | LSTM 实现糖尿病探索与预测
rnn·算法·lstm