class Solution {
public int minDistance(String word1, String word2) {
int[][] dp = new int[word1.length()+1][word2.length()+1];
for(int i=0;i<=word1.length();i++){
dp[i][0] = i;
}
for(int i=0;i<=word2.length();i++){
dp[0][i] = i;
}
for(int i=1;i<=word1.length();i++){
for(int j=1;j<=word2.length();j++){
if(word1.charAt(i-1)==word2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1];
}else{
dp[i][j] = (Math.min(dp[i-1][j],
Math.min(dp[i][j-1],dp[i-1][j-1])))+1;
}
}
}
return dp[word1.length()][word2.length()];
}
}
- 2.5
- 左上角继承(替换),上删,左插
- 虽然思路有点复杂,但其实和4.最长公共子序列差不多,
- 先是初始化第一行第一列(次数 i)
- 之后是左,左上,上三个方向最小路径
class Solution {
public int minDistance(String word1, String word2) {
int m = word1.length();
int n = word2.length();
int[][] dp = new int[m+1][n+1];
for(int i =0;i<=m;i++){
dp[i][0] = i;
}
for(int i=0;i<=n;i++){
dp[0][i] = i;
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(word1.charAt(i-1)==word2.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];
}
}

class Solution {
public int minDistance(String word1, String word2) {
int m = word1.length();
int n = word2.length();
// dp[i][j] 表示 word1的前i个 变成 word2的前j个 需要的步数
int[][] dp = new int[m + 1][n + 1];
// 1. 初始化第一列:word1 变成空字符串,只能全是删除
// "horse" -> "" : 删除 5 次
for (int i = 0; i <= m; i++) {
dp[i][0] = i;
}
// 2. 初始化第一行:空字符串 变成 word2,只能全是插入
// "" -> "ros" : 插入 3 次
for (int j = 0; j <= n; j++) {
dp[0][j] = j;
}
// 3. 推导中间状态
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
// 注意:字符串下标是从 0 开始的,所以用 i-1, j-1
if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
// 如果字符相等,不需要任何操作,直接继承“不用这俩字符”时的步数
dp[i][j] = dp[i - 1][j - 1];
} else {
// 如果字符不等,我们在三种操作里选最小的,然后 + 1
dp[i][j] = Math.min(
dp[i - 1][j - 1], // 替换 (Replace)
Math.min(
dp[i - 1][j], // 删除 (Delete)
dp[i][j - 1] // 插入 (Insert)
)
) + 1;
}
}
}
return dp[m][n];
}
}