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]
相关推荐
倒头就睡的小比特3 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼3 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光3 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark3 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her13 天前
并查集-听课笔记
笔记·算法·并查集
码流子3 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven3 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark3 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218613 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法