描述
给定两个字符串 str1 和 str2 ,请你算出将 str1 转为 str2 的最少操作数。
你可以对字符串进行3种操作:
1.插入一个字符
2.删除一个字符
3.修改一个字符。
字符串长度满足 1≤n≤1000 ,保证字符串中只出现小写英文字母。
示例1
输入:
"nowcoder","new"
返回值:
6
说明:
"nowcoder"=>"newcoder"(将'o'替换为'e'),修改操作1次 "nowcoder"=>"new"(删除"coder"),删除操作5次
示例2
输入:
"intention","execution"
返回值:
5
说明:
一种方案为: 因为2个长度都是9,后面的4个后缀的长度都为"tion",于是从"inten"到"execu"逐个修改即可
示例3
输入:
"now","nowcoder"
返回值:
5
思路分析:
该题可以使用动态规划来解决,把第一个字符串变成第二个字符串,我们需要逐个将第一个字符串的子串最少操作下变成第二个字符串,这就涉及了第一个字符串增加长度,状态转移,那可以考虑动态规划。
具体做法:
- step 1:初始条件: 假设第二个字符串为空,那很明显第一个字符串子串每增加一个字符,编辑距离就加1,这步操作是删除;同理,假设第一个字符串为空,那第二个字符串每增加一个字符,编剧距离就加1,这步操作是添加。
- step 2:状态转移: 状态转移肯定是将dp矩阵填满,那就遍历第一个字符串的每个长度,对应第二个字符串的每个长度。如果遍历到
str1[i]
和str2[j]
的位置,这两个字符相同,这多出来的字符就不用操作,操作次数与两个子串的前一个相同,因此有dp[i][j]=dp[i−1][j−1];如果这两个字符不相同,那么这两个字符需要编辑,但是此时的最短的距离不一定是修改这最后一位,也有可能是删除某个字符或者增加某个字符,因此我们选取这三种情况的最小值增加一个编辑距离,即dp[i][j]=min(dp[i−1][j−1],min(dp[i−1][j],dp[i][j−1]))+1。
图示:
代码:
import java.util.*;
public class Solution {
/**
* @param str1 string字符串
* @param str2 string字符串
* @return int整型
*/
public int editDistance (String str1, String str2) {
int n1=str1.length();
int n2=str2.length();
int[][] dp=new int[n1+1][n2+1];
//初始化边界
for(int i=0;i<=n1;i++){
dp[i][0]=i;
}
for(int i=0;i<=n2;i++){
dp[0][i]=i;
}
//遍历第一个字符串的每个位置
for(int i=1;i<=n1;i++){
//遍历第二个字符串的每个位置
for(int j=1;j<=n2;j++){
//如果字符相同,则不用编辑,直接等于前一个的距离
if(str1.charAt(i-1)==str2.charAt(j-1)){
dp[i][j]=dp[i-1][j-1];
}else{
//选取最小的距离加上此处编辑距离+1
dp[i][j]=Math.min(dp[i-1][j-1],Math.min(dp[i][j-1],dp[i-1][j]))+1;
}
}
}
return dp[n1][n2];
}
}