题目解析: DNA序列编辑距离
小R正在研究DNA序列,他需要一个函数来计算将一个受损DNA序列(dna1)转换成一个未受损序列(dna2)所需的最少编辑步骤。编辑步骤包括:增加一个碱基、删除一个碱基或替换一个碱基。
测试样例
样例1:
输入:
dna1 = "AGT",dna2 = "AGCT"
输出:1
样例2:
输入:
dna1 = "AACCGGTT",dna2 = "AACCTTGG"
输出:4
样例3:
输入:
dna1 = "ACGT",dna2 = "TGC"
输出:3
解题思路
-
问题定义: 编辑距离是指将一个字符串转换为另一个字符串所需的最小操作数。这些操作包括插入字符、删除字符和替换字符。
-
动态规划: 使用动态规划的方法来解决此问题。我们通过构建一个二维表格
dp,其中dp[i][j]表示将字符串dna1的前i个字符转换为dna2的前j个字符所需的最小编辑距离。 -
初始化:
- 创建一个大小为
(m + 1) x (n + 1)的数组dp,m和n分别是两个字符串的长度。 - 第一行和第一列分别初始化为 0 到
m和 0 到n的递增序列。这表示将空字符串转换为某个字符串所需的操作数,即仅通过插入字符实现。
- 创建一个大小为
-
填充DP表:
-
遍历
dna1和dna2的每个字符:-
如果两个字符相等,则
dp[i][j] = dp[i-1][j-1](无需任何操作)。 -
如果不相等,则取三种操作的最小值:
- 删除字符(
dp[i-1][j] + 1) - 插入字符(
dp[i][j-1] + 1) - 替换字符(
dp[i-1][j-1] + 1)
- 删除字符(
-
更新
dp[i][j]为这三种情况中的最小值。
-
-
-
结果:
- 最终,
dp[m][n]即为将dna1转换为dna2的最小编辑距离。
- 最终,
复杂度分析
- 时间复杂度:O(m * n),因为需要填充一个大小为
(m + 1) x (n + 1)的表格。 - 空间复杂度:O(min(m, n)),通过仅存储当前和前一行的数组来优化空间使用。
代码示例
以下是该思路实现的代码示例:
`def solution(dna1, dna2): m = len(dna1) n = len(dna2)
# 创建一个(m+1) x (n+1)的二维列表来保存编辑距离
dp = [[0] * (n + 1) for _ in range(m + 1)]
# 初始化第一行和第一列
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 )
print(solution("AGCCGAGC", "GCTAGCT") == 4)
Python实现细节
- 数组初始化:利用列表生成式进行初始化,确保清晰和高效。
- 循环控制:使用双重循环处理字符串的每个字符,确保状态转移的正确性。
总结
使用MarsCode AI编写代码的体验非常积极。它能够快速生成代码片段,节省了我大量的时间和精力。尤其在处理复杂算法和逻辑时,MarsCode AI提供的示例和建议帮助我更深入地理解了相关概念。此外,它的智能提示功能让我能更轻松地发现潜在的问题和优化方案。我也学会了如何利用AI工具来提升自己的编程技能,更加高效地完成项目。总的来说,MarsCode AI是我学习和工作的得力助手。