72. 编辑距离

题目:

思路:

【1】动态规划对于这种肯定是需要多增加字符串为空的时候的处理的。

代码展示:

//时间6 ms 击败 11.34%
//内存42.6 MB 击败 17.6%
//时间复杂度 :O(mn),其中 m 为 word1 的长度,n 为 word2 的长度。
//空间复杂度 :O(mn),我们需要大小为 O(mn) 的 dp 数组来记录状态值。
class Solution {
    public int minDistance(String word1, String word2) {
        int n1 = word1.length();
        int n2 = word2.length();
        // 设置动态规划结果集
        int[][] dp = new int[n1 + 1][n2 + 1];
        // 第一行,假设word1 = "";是 word1 为空变成 word2 最少步数,就是插入操作
        for (int j = 1; j <= n2; j++) dp[0][j] = dp[0][j - 1] + 1;
        // 第一列,,假设word2 = "";是 word1 为空变成 word2 需要的最少步数,就是删除操作
        for (int i = 1; i <= n1; i++) dp[i][0] = dp[i - 1][0] + 1;
        // 分析当两者都不为空
        for (int i = 1; i <= n1; i++) {
            for (int j = 1; j <= n2; j++) {
                // 如果两者当前的字符是匹配的,那么其实就不需要增加操作步骤,故直接记录到上一步的操作数即可
                if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1];
                }else {
                    // 如果两者不等,dp[i-1][j-1] 表示替换操作,dp[i-1][j] 表示删除操作,dp[i][j-1] 表示插入操作。
                    // 因为dp[i-1][j-1]相当于在之前的操作上加上把当前字符变更的操作
                    // 而dp[i-1][j] 相当于删除了word1中的这个字符,就会回到word1上个字符到当前位置的步骤
                    // 而dp[i][j-1] 相当于删除了word2中的这个字符,就会回到word2上个字符到当前位置的步骤
                    // 其实这里相当于有两个删除,为什么?因为不知道是word1更长还是word2更长
                    // 因为由长变短的操作步数和由短变长的是一样的,理论上只要确保word1更长的话可以减少一次比较
                    dp[i][j] = Math.min(Math.min(dp[i - 1][j - 1], dp[i][j - 1]), dp[i - 1][j]) + 1;
                }
            }
        }
        return dp[n1][n2];
    }
}


//相反下面这种会更直观一些
//时间2 ms击败 100%
//内存42.5 MB击败32.88%
//这种递归次数相反会比上面的更少,毕竟三次递归
//最长不过(m+n)*3,比上面的m*n会好很多
class Solution {
    public int minDistance(String word1, String word2) {
        if(word1 == null || word2 == null){
            throw new IllegalArgumentException();
          
        }

        //word1变成word2 指针指向最后一个位置 依次比较 先定义好递归函数
        //二维数组的索引有意义
        int[][] mon = new int[word1.length()][word2.length()];
        for(int[] row : mon){
            Arrays.fill(row,-1);
        }
        return doMinDistance(word1,word1.length()-1,word2,word2.length()-1,mon);
    }

    // word1 从0到l  word2 从0到r 最小编辑距离
    private int doMinDistance(String word1,int l,String word2,int r,int[][] mon){
        //l已经遍历完了 word2剩余r+1个字符 需要插入r+1;
        if(l==-1) return r+1;
        if(r==-1) return l+1;

        if(mon[l][r]!=-1){
            return mon[l][r];
        }

        if(word1.charAt(l) == word2.charAt(r)){
            mon[l][r] = doMinDistance(word1,l-1,word2,r-1,mon);
        }else {
          mon[l][r] =  min(
              //插入
            doMinDistance(word1,l,word2,r-1,mon)+1,
            //替换
            doMinDistance(word1,l-1,word2,r-1,mon)+1,
            //删除
            doMinDistance(word1,l-1,word2,r,mon)+1
        );
        }

        return mon[l][r];
    }

    private int min(int a , int b ,int c){
        return Math.min(a,Math.min(b,c));
    }
}

 

posted @ 2023-07-10 12:21  忧愁的chafry  阅读(23)  评论(0编辑  收藏  举报