代码随想录算法训练营第五十六天| 583. 两个字符串的删除操作、72. 编辑距离。

583. 两个字符串的删除操作

题目链接:力扣

题目要求:

        给定两个单词 word1 和 word2 ,返回使得 word1 和  word2 相同所需的最小步数每步 可以删除任意一个字符串中的一个字符。

示例 1:

输入: word1 = "sea", word2 = "eat"
输出: 2
解释: 第一步将 "sea" 变为 "ea" ,第二步将 "eat "变为 "ea"
  • 1 <= word1.length, word2.length <= 500
  • word1 和 word2 只包含小写英文字母

总结:

        dp[i][j]代表以i-1位置结尾的word1,以j-1位置结尾的word2,达到相同的最小删除次数,如果遍历的当前的i和j位置的元素相等的话,则不需要操作,直接继承i和j上一个状态的dp即可,如果不想等,可以删除word1的最后一个元素,也可以删除word2这边的元素,dp[i][j] 等于 删除过word1最后一个元素的dp再加上1,因为执行了一次删除操作,操作+1,或者等于 删除过word2最后一个元素的dp再加1,这两种情况取最小值,因为要得到最少的操作次数;由这些递推公式可以看出,二维数组的第一行和第一列都需要初始化,dp[0][0]代表两个字符串都空,不用操作,次数默认为0,dp[i][0],代表word2字符串为空,需要将word1字符串删除干净才使得二者相同,故需要删除i个元素,执行i次删除操作,dp[0][j]则是代表word1为空,需要删除word2的情况。

class Solution {
    public int minDistance(String word1, String word2) {
        //dp[i][j]代表以i-1位置结尾的word1,以j-1位置结尾的word2,达到相同的最小删除次数
        int[][] dp = new int[word1.length()+1][word2.length()+1];
        for(int i = 1;i <= word1.length();i++){
            dp[i][0] = i;
        }
        for(int j = 1;j <= word2.length();j++){
            dp[0][j] = j;
        }
        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{
                    //不想等,要么删除word1的这个字符,要么删除word2的这个字符
                    dp[i][j] = Math.min(dp[i-1][j]+1,dp[i][j-1]+1);
                }
            }
        }
        return dp[word1.length()][word2.length()];
    }
}

72. 编辑距离

题目链接:力扣

题目要求:

        给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数  。你可以对一个单词进行如下三种操作:

  • 插入一个字符
  • 删除一个字符
  • 替换一个字符

示例 1:

输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')
  • 0 <= word1.length, word2.length <= 500
  • word1 和 word2 由小写英文字母组成

总结:

        dp[i][j]代表以i-1为结尾的word1,与以j-1为结尾的字符串word2,变成相等的最小操作数;当遍历i和j的时候,如果遍历到的两个字符相等,则不用进行操作,直接继承i,j的上一个状态的dp即可,如果不等的时候,可删可增可替换,可增可删的情况实际上次数是一样的,删除word1,也就间接代表增加了word2,故只考虑删除的情况即可,要么删除word1的最后一个字符,要么删除word2的最后一个的字符,所以dp[i][j] = dp[i-1][j] + 1,或者 = dp[i][j-1] + 1;dp[i][j]就是等于删除一个元素时的状态的次数再加上删除这个元素的一次操作,当替换的时候,就直接拿i,和j的上一个状态的次数直接加替换的这一次操作即可。

class Solution {
    public int minDistance(String word1, String word2) {
        //1.dp[i][j]代表以i-1为结尾的word1,与以j-1为结尾的字符串word2,变成相等的最小操作数
        int[][] dp = new int[word1.length() +1][word2.length() + 1];
        //3.初始化,右递推公式可得,二维数组的第一列和第二列需做相应初始化
        for(int i = 1;i <= word1.length();i++){
            //word2为0时也就是为空时,需要word1删除当前的所有元素,i代表以i-1位置结尾,共有i个元素
            dp[i][0] = i;
        }
        for(int j = 1;j <= word2.length();j++){
            //word1为0,也就是为空时,需要word2删除当前所有元素,同样的。
            dp[0][j] = j;
        }
        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{
                    //不相等时,word1删除一个或者word2删除一个(与增加相反,故不用增加);或者替换
                    dp[i][j] = Math.min(Math.min(dp[i-1][j]+1,dp[i][j-1]+1),dp[i-1][j-1]+1);
                }
            }
        }
        return dp[word1.length()][word2.length()];
    }
}

你可能感兴趣的:(leetcode,算法,动态规划,java,数据结构)