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]
相关推荐
叩码以求索21 分钟前
浅谈:算法萌新如何高效刷题应对面试(一)
算法·面试·职场和发展
c238562 小时前
把 C++ 内存分配拆透:new 与 malloc 的三层血缘
开发语言·c++·算法
aaaameliaaa3 小时前
指针之总结
c语言·笔记·算法
宵时待雨3 小时前
优选算法专题9:哈希表
数据结构·算法·散列表
txzrxz3 小时前
最短路问题——Dijkstra 算法
数据结构·c++·算法·最短路·优先队列
gwf2163 小时前
磨损均衡算法(Wear Leveling)——SSD如何让每块闪存“公平退休“?
运维·数据库·人工智能·python·嵌入式硬件·算法·智能硬件
noipp4 小时前
推荐题目:洛谷 P6231 [JSOI2013] 公交系统
c语言·数据结构·c++·算法·游戏·洛谷·luogu
c238564 小时前
C/C++每日一练6
c语言·c++·算法
AI小码4 小时前
把动作「画」给视频世界模型,跨本体双向推演,李飞飞参与
大数据·人工智能·算法·ai·大模型·音视频·编程
KaMeidebaby6 小时前
卡梅德生物技术快报|bli亲和力检测gst:告别批量跑胶:BLI实时酶切监测技术加速GST融合蛋白下游流程优化
前端·网络·数据库·人工智能·算法