DNA序列编辑距离题解 | 豆包MarsCode AI刷题

46 阅读5分钟

问题描述

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

问题理解

需要计算将一个DNA序列 dna1 转换成另一个DNA序列 dna2 所需的最少编辑步骤。编辑步骤包括:

  1. 增加一个碱基
  2. 删除一个碱基
  3. 替换一个碱基

数据结构选择

由于我们需要计算最少的编辑步骤,动态规划(Dynamic Programming, DP)是一个合适的选择。我们可以使用一个二维的DP表来记录从 dna1 的前 i 个字符转换到 dna2 的前 j 个字符所需的最少编辑步骤。

算法步骤

  1. 初始化DP表

    • 创建一个 (m+1) x (n+1) 的二维列表 dp,其中 mdna1 的长度,ndna2 的长度。
    • dp[i][0] 表示将 dna1 的前 i 个字符转换成空字符串所需的最少步骤,显然是 i 次删除操作。
    • dp[0][j] 表示将空字符串转换成 dna2 的前 j 个字符所需的最少步骤,显然是 j 次插入操作。
  2. 填充DP表

    • 对于每个 dp[i][j],如果 dna1[i-1] == dna2[j-1],则 dp[i][j] = dp[i-1][j-1],因为不需要任何操作。
    • 否则,dp[i][j] 取以下三种操作的最小值:
      • dp[i-1][j] + 1:删除 dna1 的第 i 个字符。
      • dp[i][j-1] + 1:在 dna1 的第 i 个字符后插入 dna2 的第 j 个字符。
      • dp[i-1][j-1] + 1:将 dna1 的第 i 个字符替换为 dna2 的第 j 个字符。
  3. 返回结果

    • dp[m][n] 即为将 dna1 转换成 dna2 所需的最少编辑步骤。

总结

通过动态规划,我们可以有效地计算出将一个DNA序列转换成另一个DNA序列所需的最少编辑步骤。

代码分析

根据上述问题分析写出代码如下:

def solution(dna1, dna2):
    m = len(dna1)
    n = len(dna2)
    
    # 创建一个(m+1) x (n+1)的二维列表来保存编辑距离
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    
    # 初始化第一行和第一列
    for i in range(m + 1):
        dp[i][0] = i  # 从dna1到空字符串的操作数为i(删除操作)
    for j in range(n + 1):
        dp[0][j] = j  # 从空字符串到dna2的操作数为j(插入操作)

    # 填充DP表
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if dna1[i - 1] == dna2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1]  # 字符匹配,无需操作
            else:
                dp[i][j] = min(dp[i - 1][j] + 1,      # 删除操作
                               dp[i][j - 1] + 1,      # 插入操作
                               dp[i - 1][j - 1] + 1)  # 替换操作

    return dp[m][n]  # 返回最终的编辑距离

分析代码中用到的知识点和算法如下

知识点

  1. 动态规划(Dynamic Programming, DP)

    • 动态规划是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。它通常用于解决最优化问题。
    • 在这个问题中,我们使用动态规划来计算将一个DNA序列转换成另一个DNA序列所需的最少编辑步骤。
  2. 二维数组(2D Array)

    • 二维数组是一种常见的数据结构,用于存储表格形式的数据。
    • 在这个问题中,我们使用一个 (m+1) x (n+1) 的二维数组 dp 来存储从 dna1 的前 i 个字符转换到 dna2 的前 j 个字符所需的最少编辑步骤。
  3. 字符串操作

    • 字符串操作包括字符串的比较、插入、删除和替换等操作。
    • 在这个问题中,我们需要比较两个字符串的字符,并根据比较结果进行相应的操作(插入、删除、替换)。

算法

  1. 编辑距离算法(Levenshtein Distance)

    • 编辑距离算法用于计算两个字符串之间的最小编辑距离,即从一个字符串转换到另一个字符串所需的最少编辑步骤。
    • 在这个问题中,我们使用编辑距离算法来计算将 dna1 转换成 dna2 所需的最少编辑步骤。
  2. 初始化DP表

    • 我们首先初始化DP表的第一行和第一列,表示从 dna1 到空字符串和从空字符串到 dna2 的编辑距离。
    • dp[i][0] = i 表示从 dna1 的前 i 个字符转换成空字符串需要 i 次删除操作。
    • dp[0][j] = j 表示从空字符串转换成 dna2 的前 j 个字符需要 j 次插入操作。
  3. 填充DP表

    • 我们使用双重循环遍历 dna1dna2 的所有字符。
    • 如果 dna1[i-1] == dna2[j-1],则 dp[i][j] = dp[i-1][j-1],因为不需要任何操作。
    • 否则,dp[i][j] 取以下三种操作的最小值,并加1:
      • dp[i-1][j] + 1:删除 dna1 的第 i 个字符。
      • dp[i][j-1] + 1:在 dna1 的第 i 个字符后插入 dna2 的第 j 个字符。
      • dp[i-1][j-1] + 1:将 dna1 的第 i 个字符替换为 dna2 的第 j 个字符。
  4. 返回结果

    • dp[m][n] 即为将 dna1 转换成 dna2 所需的最少编辑步骤。

总结

这段代码主要使用了动态规划和编辑距离算法来解决将一个DNA序列转换成另一个DNA序列所需的最少编辑步骤问题。通过初始化DP表和填充DP表,我们可以有效地计算出最小编辑距离。