题目解析:古生物DNA序列血缘分析| 豆包MarsCode AI刷题

98 阅读2分钟

问题描述

在古生物学的研究中,比较物种间 DNA 序列的差异可以用来分析血缘关系。小小是一位古生物学家,她通过对比 DNA 序列(由字符 A、C、G、T 组成)的差异来衡量物种间的亲疏远近关系。两条 DNA 序列间的差异可以通过以下三种操作来定义:

•	插入:在序列中增加一个字符;
•	删除:从序列中移除一个字符;
•	替换:将序列中的一个字符替换为另一个字符。

两条 DNA 序列间的最小变异次数(即需要的最小编辑操作数)越小,表示两者血缘关系越接近。我们的任务是实现一个算法,计算两条 DNA 序列之间的最小变异次数。

问题建模

这个问题可以用经典的 编辑距离(Edit Distance) 动态规划算法来解决。动态规划的核心是构造一个二维数组 dp,其中 dp[i][j] 表示将 dna1 的前 i 个字符转换为 dna2 的前 j 个字符所需的最小编辑操作数。

状态转移方程:

•	如果 dna1[i-1] == dna2[j-1],则 dp[i][j] = dp[i-1][j-1],因为当前字符相等,无需额外操作;
•	否则,取以下三种操作的最小值:
1.	插入:dp[i][j-1] + 1
2.	删除:dp[i-1][j] + 1
3.	替换:dp[i-1][j-1] + 1

边界条件:

•	dp[0][j] = j:将空字符串转换为 dna2 的前 j 个字符需要插入 j 次;
•	dp[i][0] = i:将 dna1 的前 i 个字符转换为空字符串需要删除 i 次。

算法实现

以下是该问题的 Python 代码实现:

截屏2024-11-28 13.18.41.png

测试结果分析

•	样例 1:
•	输入:dna1 = "AGT", dna2 = "AGCT"
•	输出:1
•	分析:只需要在 "AGT" 末尾插入一个字符 'C'。
•	样例 2:
•	输入:dna1 = "AACCGGTT", dna2 = "AACCTTGG"
•	输出:4
•	分析:需要替换 'G' -> 'T' 两次,并交换 'T''G' 的位置,总共4次操作。
•	样例 3:
•	输入:dna1 = "ACGT", dna2 = "TGC"
•	输出:3
•	分析:需要删除 'A',替换 'C' -> 'G',以及替换 'T' -> 'C'。
•	样例 4:
•	输入:dna1 = "", dna2 = "ACGT"
•	输出:4
•	分析:需要插入 'A', 'C', 'G', 'T',共4次操作。

复杂度分析

•	时间复杂度:O(m * n),其中 m 和 n 分别是 dna1 和 dna2 的长度。动态规划需要遍历整个二维表。
•	空间复杂度:O(m * n),用于存储动态规划表。

总结

本题通过经典的动态规划方法解决编辑距离问题,有着广泛的应用场景,例如 DNA 序列比对、拼写纠错和文本比较等。该算法逻辑清晰且高效,非常适合作为学习动态规划的入门案例。在实际应用中,可以通过优化空间复杂度进一步提升性能,例如使用滚动数组代替二维数组存储。