首先理解问题:小R正在研究DNA序列,他需要一个函数来计算将一个受损DNA序列(dna1)转换成一个未受损序列(dna2)所需的最少编辑步骤。编辑步骤包括:增加一个碱基、删除一个碱基或替换一个碱基。
理解:- 你需要计算将一个受损DNA序列(dna1)转换成一个未受损序列(dna2)所需的最少编辑步骤。编辑步骤包括增加一个碱基、删除一个碱基或替换一个碱基。
- 第一步:初始化:
dp[i][0] = i:将 dna1 的前 i 个字符转换为空字符串需要删除 i 个字符。
dp[0][j] = j:将空字符串转换为 dna2 的前 j 个字符需要添加 j 个字符。
- 第二步:状态转移:
如果 dna1[i-1] == dna2[j-1],则 dp[i][j] = dp[i-1][j-1]。
否则,dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1,分别对应替换、删除和插入操作。
- 第三步:最终结果:
dp[m][n] 即为将 dna1 转换为 dna2 所需的最少编辑步骤。
代码实现
public static int solution(String dna1, String dna2) {
int m = dna1.length();
int n = dna2.length();
int[][] dp = new int[m + 1][n + 1];
for (int i = 0; i <= m; i++) {
dp[i][0] = i;
}
for (int j = 0; j <= n; j++) {
dp[0][j] = j;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (dna1.charAt(i - 1) == dna2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i][j - 1])) + 1;
}
}
}
return dp[m][n];
}
public static void main(String[] args) {
System.out.println(solution("AGCTTAGC", "AGCTAGCT") == 2);
System.out.println(solution("AGCCGAGC", "GCTAGCT") == 4);
}
}
-总结:这个问题通过动态规划解决,使用二维数组 dp 记录从 dna1 转换到 dna2 的最少编辑步骤。初始化 dp[i][0] 和 dp[0][j] 为 i 和 j,表示删除和插入操作。状态转移时,若字符相同则 dp[i][j] = dp[i-1][j-1],否则取替换、删除、插入中的最小值加一。最终结果为 dp[m][n]。