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];
    }
}