1.题目描述
问题描述
小R正在研究DNA序列,他需要一个函数来计算将一个受损DNA序列(dna1)转换成一个未受损序列(dna2)所需的最少编辑步骤。编辑步骤包括:增加一个碱基、删除一个碱基或替换一个碱基。
示例1
输入:dna1 = "AACCGGTT",dna2 = "AACCTTGG" 输出:4
示例2
输入:dna1 = "ACGT",dna2 = "TGC" 输出:3
难度等级
简单
题目链接
2.解题思路
创立一个二维数组,进行加减操作,从上一步最小的基础上再加一步,一直迭代到最后一个碱基,取最小值即为答案。
dp=[[0]*(len2+1) for _ in range(len1+1)]创建一个dp数组,大小为(len1+1)*(len2+1),
初始化 dp 数组的第一行和第一列
for i in range(len1+1):
dp[i][0]=i
for j in range(len2+1):
dp[0][j]=j
再进行迭代,要注意下面要用到i-1和j-1,所以从迭代时要1开始。然后分两种情况,即碱基一致时,不进行操作;碱基不一致时,选择插入(dp[i][j-1])、删除(dp[i-1][j])或替换(dp[i-1][j-1])操作的最小值加1
for i in range(1,len1+1):
for j in range(1,len2+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],dp[i][j-1],dp[i-1][j-1])+1
最后返回从dna1到dna2的最小编辑距离即dp[len1][len2]
3.代码实现
def solution(dna1, dna2):
# Please write your code here
len1=len(dna1)
len2=len(dna2)
dp=[[0]*(len2+1) for _ in range(len1+1)]#创建一个dp数组并初始化,大小为(len1+1)*(len2+1)
for i in range(len1+1)://只进行删除操作
dp[i][0]=i
for j in range(len2+1)://只进行插入操作
dp[0][j]=j
for i in range(1,len1+1)://注意下面要用到i-1和j-1,所以从1开始。
for j in range(1,len2+1):
if dna1[i-1]==dna2[j-1]://碱基一致时,不进行操作
dp[i][j]=dp[i-1][j-1]
else://否则,我们选择插入(dp[i][j-1])、删除(dp[i-1][j])或替换(dp[i-1][j-1])操作的最小值加1
dp[i][j]=min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1
return dp[len1][len2]//返回从dna1到dna2的最小编辑距离
if __name__ == "__main__":
# You can add more test cases here
print(solution("AGCTTAGC", "AGCTAGCT") == 2 )
print(solution("AGCCGAGC", "GCTAGCT") == 4)
4.总结
以上是我对这道题的解法,主要运用dp动态规划,有更好的方法希望可以指教,谢谢你观看到这里,祝大家刷题顺利。