问题描述:已知两个字符串word1
和word2
,求从word1转化成word2最少需要几步。
其中,每一步只能进行以下三个操作之一:
- 插入一个字符
- 删除一个字符
- 替换一个字符
用动态规划的思路,用dp[i][j]
表示word1的前i个字符转化为word2的前j个字符需要的操作次数。
根据word1
和word2
的最后一个字符是否相同,分为两种情况:
1、word1[i] == word2[j]:那么同时去掉最后一个字符,不影响结果,故dp[i][j] = dp[i-1][j-1]
2、word1[i] != word2[j]:可以用如下三种方法进行操作:
①将word1转化为word2的前j-1个字符,再将word2的最后一个字符插入到word1末尾。即步骤为dp[i][j-1]+1
②将word1的前i-1个字符转化为word2,再将word1的最后一个字符删除。即步骤为dp[i-1][j]+1
③将word1的前i-1个字符转化为word2的前j-1个字符,再将word1的第i个字符替换为word2的第j个字符,即步骤为dp[i-1][j-1]+1。
dp[i][j]为三种方法的最小值,即dp[i][j] = min(dp[i][j-1]+1, dp[i-1][j]+1, dp[i-1][j-1]+1)。
public class MinDistance {
public static int Min(String s1,String s2){
int m = s1.length();
int n = s2.length();
int[][] dp = new int[m+1][n+1];
for(int i = 1;i <= m;i++){
dp[i][0] = i;
}
for(int i = 1;i <= n;i++){
dp[0][i] = i;
}
// 自底向上求解
for(int i = 1;i <= m;i++){
for(int j = 1;j <= n;j++){
if(s1.charAt(i-1) == s2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1]; // 对应相等,直接跳过
}else{
//dp[i-1][j]+1 删除操作
//dp[i][j-1]+1 插入操作
//dp[i-1][j-1]+1 替换操作
dp[i][j] = Math.min
(dp[i-1][j]+1, Math.min(dp[i][j-1]+1, dp[i-1][j-1]+1));
}
}
}
// 储存最小值
return dp[m][n];
}
public static void main(String[] args) {
String s1 = "rad";
String s2 = "apple";
int min = Min(s1, s2);
System.out.println(min);
}
}