古生物血缘分析| 豆包MarsCode AI刷题

63 阅读3分钟

问题描述

小U是一位古生物学家,正在研究不同物种之间的血缘关系。为了分析两种古生物的血缘远近,她需要比较它们的DNA序列。DNA由四种核苷酸A、C、G、T组成,并且可能通过三种方式发生变异:添加一个核苷酸、删除一个核苷酸或替换一个核苷酸。小U认为两条DNA序列之间的最小变异次数可以反映它们之间的血缘关系:变异次数越少,血缘关系越近。

你的任务是编写一个算法,帮助小U计算两条DNA序列之间所需的最小变异次数。

  • dna1: 第一条DNA序列。
  • dna2: 第二条DNA序列。

测试样例

样例1:

输入:dna1 = "AGT",dna2 = "AGCT"
输出:1

样例2:

输入:dna1 = "AACCGGTT",dna2 = "AACCTTGG"
输出:4

样例3:

输入:dna1 = "ACGT",dna2 = "TGC"
输出:3

样例4:

输入:dna1 = "A",dna2 = "T"
输出:1

样例5:

输入:dna1 = "GGGG",dna2 = "TTTT"
输出:4

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)

这个代码的目标是计算两条DNA序列之间的最小变异次数。变异操作包括添加、删除和替换核苷酸。这个问题可以通过动态规划来解决,因为我们需要找到从一个序列转换到另一个序列的最小操作次数。

数据结构选择

我们选择使用一个二维数组 dp 来存储动态规划的结果。dp[i][j] 表示将 dna1 的前 i 个字符转换为 dna2 的前 j 个字符所需的最小操作次数。

算法步骤

  1. 初始化

    • 创建一个 (m+1) x (n+1) 的二维数组 dp,其中 mn 分别是 dna1dna2 的长度。
    • 初始化第一行和第一列:
      • dp[0][j] 表示将空字符串转换为 dna2 的前 j 个字符,需要 j 次添加操作。
      • dp[i][0] 表示将 dna1 的前 i 个字符转换为空字符串,需要 i 次删除操作。
  2. 状态转移

    • 对于每个 dp[i][j],如果 dna1[i-1] == dna2[j-1],则不需要额外操作,dp[i][j] = dp[i-1][j-1]
    • 否则,取三种操作中的最小值:
      • 替换操作:dp[i-1][j-1] + 1
      • 删除操作:dp[i-1][j] + 1
      • 添加操作:dp[i][j-1] + 1
  3. 结果

  • 最终结果存储在 dp[m][n] 中,表示将 dna1 转换为 dna2 所需的最小操作次数

这些是今天11.23的总结了,还在学习ai课程中……