伴学笔记 AI刷题 25.DNA序列编辑距离 | 豆包MarsCode AI刷题

这道题虽然标的是简单,但是是一道很经典的DP问题,接下来将详细讲解。

问题描述

小R正在研究DNA序列,他需要一个函数来计算将一个受损DNA序列(dna1)转换成一个未受损序列(dna2)所需的最少编辑步骤。编辑步骤包括:增加一个碱基、删除一个碱基或替换一个碱基。


测试样例

样例1:

输入:dna1 = "AGT",dna2 = "AGCT"

输出:1

样例2:

输入:dna1 = "AACCGGTT",dna2 = "AACCTTGG"

输出:4

样例3:

输入:dna1 = "ACGT",dna2 = "TGC"

输出:3

样例4:

输入:dna1 = "A",dna2 = "T"

输出:1

样例5:

输入:dna1 = "GGGG",dna2 = "TTTT"

输出:4

问题分析

小R的DNA序列编辑问题是一个典型的编辑距离问题,也称为Levenshtein距离问题。编辑距离是指将一个字符串转换成另一个字符串所需的最少编辑操作步骤,包括增加一个字符、删除一个字符或替换一个字符。

解题思路

  1. 定义状态

    • dp[i][j] 表示将字符串 dna1 的前 i 个字符转换成字符串 dna2 的前 j 个字符所需的最少编辑步骤。
  2. 状态转移

    • 对于字符串 dna1 的第 i 个字符和字符串 dna2 的第 j 个字符,我们有以下几种情况:

      • 如果 dna1[i-1] == dna2[j-1],则不需要编辑操作,dp[i][j] = dp[i-1][j-1]
      • 如果 dna1[i-1] != dna2[j-1],则需要进行替换操作,dp[i][j] = dp[i-1][j-1] + 1
      • 如果我们删除 dna1 的第 i 个字符,则 dp[i][j] = dp[i-1][j] + 1
      • 如果我们在 dna1 的第 i 个字符后增加一个字符,则 dp[i][j] = dp[i][j-1] + 1
    • 因此,dp[i][j] 的值是上述几种情况的最小值。

  3. 初始化

    • dp[0][j] = j,因为将一个空字符串转换成长度为 j 的字符串需要进行 j 次增加操作。
    • dp[i][0] = i,因为将长度为 i 的字符串转换成一个空字符串需要进行 i 次删除操作。
  4. 计算顺序

    • 我们从左到右、从上到下遍历动态规划表,确保在计算 dp[i][j] 时,其左侧、上方和左上方的值已经被计算过。
  5. 返回结果

    • 最终结果为 dp[l1][l2],即将整个字符串 dna1 转换成整个字符串 dna2 所需的最少编辑步骤。

解题代码

python 复制代码
def solution(dna1, dna2):
    l1 = len(dna1)
    l2 = len(dna2)
    
    # 初始化动态规划表
    dp = [[0] * (l2 + 1) for _ in range(l1 + 1)]
    
    # 初始化第一行和第一列
    for i in range(l1 + 1):
        dp[i][0] = i
    for j in range(l2 + 1):
        dp[0][j] = j
    
    # 填充动态规划表
    for i in range(1, l1 + 1):
        for j in range(1, l2 + 1):
            dp[i][j] = min(dp[i-1][j] + 1, dp[i][j-1] + 1)
            if dna1[i-1] == dna2[j-1]:
                dp[i][j] = min(dp[i][j], dp[i-1][j-1])
            else:
                dp[i][j] = min(dp[i][j], dp[i-1][j-1] + 1)
    
    return dp[l1][l2]

if __name__ == "__main__":
    # 你可以在这里添加更多的测试用例
    print(solution("AGCTTAGC", "AGCTAGCT") == 2)
    print(solution("AGCCGAGC", "GCTAGCT") == 4)

总结

  1. 时间复杂度

    • 我们需要遍历整个动态规划表,其大小为 (l1 + 1) * (l2 + 1)。
    • 因此,总的时间复杂度是 O(l1 * l2)。
  2. 空间复杂度

    • 我们需要一个二维数组 dp 来存储状态,其大小为 (l1 + 1) * (l2 + 1)。
    • 因此,总的空间复杂度是 O(l1 * l2)。

这个问题在生物信息学、自然语言处理和计算机科学等领域有着广泛的应用。

相关推荐
Find4 天前
MaxKB 集成langchain + Vue + PostgreSQL 的 本地大模型+本地知识库 构建私有大模型 | MarsCode AI刷题
青训营笔记
理tan王子4 天前
伴学笔记 AI刷题 14.数组元素之和最小化 | 豆包MarsCode AI刷题
青训营笔记
理tan王子4 天前
伴学笔记 AI刷题 9.超市里的货物架调整 | 豆包MarsCode AI刷题
青训营笔记
夭要7夜宵6 天前
分而治之,主题分片Partition | 豆包MarsCode AI刷题
青训营笔记
三六7 天前
刷题漫漫路(二)| 豆包MarsCode AI刷题
青训营笔记
tabzzz8 天前
突破Zustand的局限性:与React ContentAPI搭配使用
前端·青训营笔记
Serendipity5659 天前
Go 语言入门指南——单元测试 | 豆包MarsCode AI刷题;
青训营笔记
wml11 天前
前端实践-使用React实现简单代办事项列表 | 豆包MarsCode AI刷题
青训营笔记
用户447103089324212 天前
详解前端框架中的设计模式 | 豆包MarsCode AI刷题
青训营笔记