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

25 阅读3分钟

代码思路解析

问题背景

给定两个DNA序列dna1dna2,我们需要计算将dna1转换为dna2所需的最小操作次数。允许的操作包括插入一个字符、删除一个字符和替换一个字符。

解决方案

这个问题可以通过动态规划(Dynamic Programming, DP)来解决。动态规划的核心思想是将大问题分解为小问题,并通过存储中间结果来避免重复计算。

具体步骤

  1. 定义状态

    • 定义一个二维数组dp,其中dp[i][j]表示将dna1的前i个字符转换为dna2的前j个字符所需的最小操作次数。
  2. 初始化边界条件

    • dp[i][0]表示将dna1的前i个字符转换为空字符串,需要i次删除操作。
    • dp[0][j]表示将空字符串转换为dna2的前j个字符,需要j次插入操作。
  3. 状态转移方程

    • 如果dna1[i-1] == dna2[j-1],即当前字符相同,不需要任何操作,直接继承之前的操作次数:dp[i][j] = dp[i-1][j-1]

    • 如果dna1[i-1] != dna2[j-1],需要考虑三种操作:

      • 插入:dp[i][j-1] + 1
      • 删除:dp[i-1][j] + 1
      • 替换:dp[i-1][j-1] + 1
    • 选择上述三种操作中的最小值作为dp[i][j]的值。

  4. 返回结果

    • 最终结果存储在dp[m][n]中,即dp数组的最后一个元素,表示将整个dna1转换为整个dna2所需的最小操作次数。

代码实现

python
深色版本
def min_operations_to_restore_dna(dna1, dna2):
    # 获取两个DNA序列的长度
    m, n = len(dna1), len(dna2)
    
    # 创建一个二维数组dp,dp[i][j]代表将dna1的前i个字符转换成dna2的前j个字符所需的最小操作次数
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    
    # 初始化dp数组
    for i in range(m + 1):
        dp[i][0] = i  # 将dna1的前i个字符转换为空字符串,需要i次删除操作
    for j in range(n + 1):
        dp[0][j] = j  # 将空字符串转换为dna2的前j个字符,需要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:
                # 取插入、删除、替换操作中的最小值,并加1(代表当前这次操作)
                dp[i][j] = min(dp[i - 1][j] + 1,    # 删除dna1的一个字符
                               dp[i][j - 1] + 1,    # 在dna1中插入一个字符
                               dp[i - 1][j - 1] + 1 # 替换dna1的一个字符
                              )
    
    # dp[m][n]即将dna1转换为dna2所需的最小操作次数
    return dp[m][n]

# 验证示例
def test_examples():
    # 示例1
    dna1_example1 = "AGCTTAGC"
    dna2_example1 = "AGCTAGCT"
    print(f"示例1输入:")
    print(f"dna1: {dna1_example1}")
    print(f"dna2: {dna2_example1}")
    print(f"输出: {min_operations_to_restore_dna(dna1_example1, dna2_example1)} (期望输出: 2)\n")
    
    # 示例2
    dna1_example2 = "AGCCGAGC"
    dna2_example2 = "GCTAGCT"
    print(f"示例2输入:")
    print(f"dna1: {dna1_example2}")
    print(f"dna2: {dna2_example2}")
    print(f"输出: {min_operations_to_restore_dna(dna1_example2, dna2_example2)} (期望输出: 4)\n")

# 调用测试函数
test_examples()