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]
相关推荐
zx_7414848123 分钟前
YOLOv3 核心原理详解:Darknet-53 架构、多尺度预测与 FPN 特征融合
算法·yolo·目标检测·yolov3
MoRanzhi120323 分钟前
122.四平方和(暴力枚举)
python·数学·算法·蓝桥杯·完全平方数·暴力枚举·四平方和定理
倒头就睡的小比特24 分钟前
贪心算法介绍
算法·贪心算法
万少1 小时前
Qoder sonus模型 20分钟,复刻 马斯克 飞天汽车
前端·后端·算法
七牛云行业应用1 小时前
Muse Spark Open 发布:Meta 称其为美国最强开放权重模型,816B 参数如何落地
算法
esop轻Mes看板亮灯分拣ESD静电安2 小时前
产线“最后一米”的破局密码:ESOP与MES的区别与深度协同
算法
陈天伟教授2 小时前
《数据处理和标注技术》课程能力图谱
人工智能·算法
LMT_Lanmantech2 小时前
HyperWorks许可:almutil显示Unit满了,数据到底准不准?
运维·服务器·算法
禁默2 小时前
论文解读与思考:基于场所地图的标识感知机器人探索方法及工程参考的价值
人工智能·深度学习·算法·机器人
维克兜率天2 小时前
【维克】统计套利建模:从因子到信号的完整流程
android·开发语言·python·算法·kotlin