题目分析与解题思路 题目概述 给定两个DNA字符串 dna1 和 dna2,要求计算将 dna1 转换成 dna2 所需的最小编辑距离。编辑操作包括插入一个字符、删除一个字符、替换一个字符。 解题思路 这个问题是经典的动态规划问题,通常称为“编辑距离”或“Levenshtein距离”。我们可以使用一个二维数组 dp 来存储从 dna1 的前 i 个字符转换成 dna2 的前 j 个字符所需的最小编辑距离。 初始化 dp 数组:当 dna1 为空字符串时,将空字符串转换成 dna2 的前 j 个字符需要 j 次插入操作。 当 dna2 为空字符串时,将 dna1 的前 i 个字符转换成空字符串需要 i 次删除操作。 填充 dp 数组:对于 dp[i][j],如果 dna1[i-1] == dna2[j-1],则不需要编辑,dp[i][j] = dp[i-1][j-1]。 如果 dna1[i-1] != dna2[j-1],则考虑三种操作:删除 dna1[i-1],然后计算 dp[i-1][j]。 插入 dna2[j-1] 到 dna1 的末尾(等价于将 dna1[i-1] 视为不匹配并跳过,然后计算 dp[i][j-1])。 替换 dna1[i-1] 为 dna2[j-1],然后计算 dp[i-1][j-1]。 取这三种操作中的最小值,并加1(表示当前这一步的编辑操作),作为 dp[i][j] 的值。 返回结果:最终,dp[m][n] 存储了将 dna1 的所有字符转换成 dna2 的所有字符所需的最小编辑距离。 图解 假设 dna1 = "AGCTTAGC",dna2 = "AGCTAGCT": 初始化 dp 数组: 空AGCTTAGC空012345678A1G2C3T4A5G6C7T8 填充 dp 数组(部分):当 i=1, j=1 时,dna1[0] == dna2[0],所以 dp[1][1] = dp[0][0] = 0。 类似地,填充其他单元格,直到完成整个数组。 (由于篇幅限制,完整的 dp 数组填充过程在此省略,但可以通过上述规则逐步填充。) 代码详解 python复制代码 def solution(dna1, dna2): m, n = len(dna1), len(dna2)
创建一个 (m+1) x (n+1) 的二维数组 dp
dp = [[0] * (n + 1) for _ in range(m + 1)]
初始化 dp 数组
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] if name == "main":
测试用例
print(solution("AGCTTAGC", "AGCTAGCT") == 2) # 输出 True,因为最小编辑距离为2 print(solution("AGCCGAGC", "GCTAGCT") == 4) # 输出 True,因为最小编辑距离为4 总结 本题通过动态规划的思想,利用二维数组 dp 存储中间结果,逐步计算出将 dna1 转换成 dna2 所需的最小编辑距离。这种方法虽然空间复杂度较高(O(mn)),但时间复杂度也是O(mn),且能够清晰地展示问题的求解过程。在实际应用中,可以根据具体情况选择是否对空间进行优化。