问题描述
小U是一位古生物学家,正在研究不同物种之间的血缘关系。为了分析两种古生物的血缘远近,她需要比较它们的DNA序列。DNA由四种核苷酸A、C、G、T组成,并且可能通过三种方式发生变异:添加一个核苷酸、删除一个核苷酸或替换一个核苷酸。小U认为两条DNA序列之间的最小变异次数可以反映它们之间的血缘关系:变异次数越少,血缘关系越近。
你的任务是编写一个算法,帮助小U计算两条DNA序列之间所需的最小变异次数。
dna1: 第一条DNA序列。
dna2: 第二条DNA序列。
def solution(dna1, dna2):
# 获取两个DNA序列的长度
m = len(dna1)
n = len(dna2)
# 创建动态规划表格
# dp[i][j] 表示将dna1的前i个字符转换为dna2的前j个字符所需的最小操作次数
dp = [[0] * (n + 1) for _ in range(m + 1)]
# 初始化第一行和第一列
# 第一行:将空字符串转换为dna2的前j个字符需要j次添加操作
for j in range(n + 1):
dp[0][j] = j
# 第一列:将dna1的前i个字符转换为空字符串需要i次删除操作
for i in range(m + 1):
dp[i][0] = i
# 填充动态规划表格
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-1][j-1] + 1
# 2. 删除操作:dp[i-1][j] + 1
# 3. 添加操作:dp[i][j-1] + 1
dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1
# 返回最终结果
return dp[m][n]
if __name__ == "__main__":
# You can add more test cases here
print(solution("AGT", "AGCT") == 1)
print(solution("", "ACGT") == 4)
print(solution("GCTAGCAT", "ACGT") == 5)