LC 72. 编辑距离 + LC 583. 两个字符串的删除操作 + LC 712. 两个字符串的最小ASCII删除和

https://www.cnblogs.com/masterlibin/p/5785092.html

LC 72. 编辑距离

给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

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

示例 1:

输入: word1 = “horse”, word2 = “ros”
输出: 3
解释:
horse -> rorse (将 ‘h’ 替换为 ‘r’)
rorse -> rose (删除 ‘r’)
rose -> ros (删除 ‘e’)

示例 2:

输入: word1 = “intention”, word2 = “execution”
输出: 5
解释:
intention -> inention (删除 ‘t’)
inention -> enention (将 ‘i’ 替换为 ‘e’)
enention -> exention (将 ‘n’ 替换为 ‘x’)
exention -> exection (将 ‘n’ 替换为 ‘c’)
exection -> execution (插入 ‘u’)

算法分析:

也就是说,就是将一个字符串变成另外一个字符串所用的最少操作数,每次只能增加、删除或者替换一个字符。
首先我们令word1和word2分别为:michaelab和michaelxy(为了理解简单,我们假设word1和word2字符长度是一样的),dis[i][j]作为word1和word2之间的Edit Distance,我们要做的就是求出michaelx到michaely的最小steps。

首先解释下dis[i][j]:它是指word1[i]和word2[j]的Edit Distance。dis[0][0]表示word1和word2都为空的时候,此时他们的Edit Distance为0。很明显可以得出的,dis[0][j]就是word1为空,word2长度为j的情况,此时他们的Edit Distance为j,也就是从空,添加 j个字符转换成word2的最小Edit Distance为j;同理dis[i][0]就是,word1长度为i,word2为空时,word1需要 删除 i个字符才能转换成空,所以转换成word2的最小Edit Distance为i。下面及时初始化代码:

   for (int i = 0; i < row; i++) dis[i][0] = i;
   for (int j = 0; j < col; j++)	dis[0][j] = j;

下面来分析下题目规定的三个操作:添加,删除,替换。

假设word1[i]和word2[j](此处i = j)分别为:michaelab和michaelxy

显然如果b==y, 那么dis[i][j] = dis[i-1][j-1]。

如果b!=y,那么:

添加: 也就是在michaelab后面添加一个y,那么word1就变成了michaelaby,此时

dis[i][j] = 1 + dis[i][j-1];

上式中,1代表刚刚的添加操作,添加操作后,word1变成michaelaby,word2为michaelxy。dis[i][j-1]代表从word[i]转换成word[j-1]的最小Edit Distance,也就是michaelab转换成michaelx的最小Edit Distance,由于两个字符串尾部的y==y,所以只需要将michaelab变成michaelx就可以了,而他们之间的最小Edit Distance就是dis[i][j-1]。

删除: 也就是将michaelab后面的b删除,那么word1就变成了michaela,此时

dis[i][j] = 1 + dis[i-1][j];

上式中,1代表刚刚的删除操作,删除操作后,word1变成michaela,word2为michaelxy。dis[i-1][j]代表从word[i-1]转换成word[j]的最小Edit Distance,也就是michaela转换成michaelxy的最小Edit Distance,所以只需要将michaela变成michaelxy就可以了,而他们之间的最小Edit Distance就是dis[i-1][j]。

替换: 也就是将michaelab后面的b替换成y,那么word1就变成了michaelay,此时

dis[i][j] = 1 + dis[i-1][j-1];

上式中,1代表刚刚的替换操作,替换操作后,word1变成michaelay,word2为michaelxy。dis[i-1][j-1]代表从word[i-1]转换成word[j-1]的最小Edit Distance,也即是michaelay转换成michaelxy的最小Edit Distance,由于两个字符串尾部的y==y,所以只需要将michaela变成michaelx就可以了,而他们之间的最小Edit Distance就是dis[i-1][j-1]。

/*求出dp[i][j]在进行:增,删,替换的时候,与上一个的 dp 关系
if x == y, then dp[i][j] == dp[i-1][j-1]
if x != y, and we insert y for word1, then dp[i][j] = dp[i][j-1] + 1
if x != y, and we delete x for word1, then dp[i][j] = dp[i-1][j] + 1
if x != y, and we replace x with y for word1, then dp[i][j] = dp[i-1][j-1] + 1
When x!=y, dp[i][j] is the min of the three situations.
Initial condition:
dp[i][0] = i, dp[0][j] = j
*/
    public int minDistance(String word1, String word2) {
        int[][] dp=new int[word1.length()+1][word2.length()+1];
        for(int i=1;i<=word1.length();i++){
            dp[i][0]=i;//word1删除元素
        }
        for(int j=1;j<=word2.length();j++){
            dp[0][j]=j;//word1添加元素
        }
        for(int i=0;i<word1.length();i++){
            for(int j=0;j<word2.length();j++){
                if(word1.charAt(i)==word2.charAt(j))
                    dp[i+1][j+1]=dp[i][j];
                else{
                    int insert=dp[i+1][j]+1;
                    int delete=dp[i][j+1]+1;
                    int replace=dp[i][j]+1;
                    int min=insert>delete?delete:insert;
                    min=min>replace?replace:min;
                    dp[i+1][j+1]=min;
                }
            }
        }
        return dp[word1.length()][word2.length()];
    }

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

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

示例 1:

输入: “sea”, “eat”
输出: 2
解释: 第一步将"sea"变为"ea",第二步将"eat"变为"ea"

说明:

  • 给定单词的长度不超过500。
  • 给定单词中的字符只含有小写字母。
// 583. 两个字符串的删除操作
    public int minDistance(String word1, String word2) {
        int[][] dp=new int[word1.length()+1][word2.length()+1];
        for(int i=1;i<=word1.length();i++){
            dp[i][0]=i;//删除i个字符
        }
        for(int j=1;j<=word2.length();j++){
            dp[0][j]=j;//删除j个字符
        }

        for(int i=0;i<word1.length();i++){
            for(int j=0;j<word2.length();j++){
                if(word1.charAt(i)==word2.charAt(j)){
                    dp[i+1][j+1]=dp[i][j];
                }else{
                    int del1=dp[i][j+1]+1;
                    int del2=dp[i+1][j]+1;
                    dp[i+1][j+1]= Math.min(del1,del2);
                }
            }
        }
        return dp[word1.length()][word2.length()];
    }

LC 712. 两个字符串的最小ASCII删除和

给定两个字符串s1, s2,找到使两个字符串相等所需删除字符的ASCII值的最小和。

示例 1:

输入: s1 = “sea”, s2 = “eat”
输出: 231
解释: 在 “sea” 中删除 “s” 并将 “s” 的值(115)加入总和。
在 “eat” 中删除 “t” 并将 116 加入总和。
结束时,两个字符串相等,115 + 116 = 231 就是符合条件的最小和。

示例 2:

输入: s1 = “delete”, s2 = “leet”
输出: 403
解释: 在 “delete” 中删除 “dee” 字符串变成 “let”,
将 100[d]+101[e]+101[e] 加入总和。在 “leet” 中删除 “e” 将 101[e] 加入总和。
结束时,两个字符串都等于 “let”,结果即为 100+101+101+101 = 403 。
如果改为将两个字符串转换为 “lee” 或 “eet”,我们会得到 433 或 417 的结果,比答案更大。

注意:

  • 0 < s1.length, s2.length <= 1000。
  • 所有字符串中的字符ASCII值在[97, 122]之间。
//712. 两个字符串的最小ASCII删除和
    public int minimumDeleteSum(String s1, String s2) {
        int[][] dp=new int[s1.length()+1][s2.length()+1];
        for(int i=1;i<=s1.length();i++){
            dp[i][0]=dp[i-1][0]+s1.charAt(i-1);//删除i个字符,注意s1.charAt(i-1),是i-1哦
        }
        for(int j=1;j<=s2.length();j++){
            dp[0][j]=dp[0][j-1]+s2.charAt(j-1);//删除j个字符
        }

        for(int i=0;i<s1.length();i++){
            for(int j=0;j<s2.length();j++){
                if(s1.charAt(i)==s2.charAt(j)){
                    dp[i+1][j+1]=dp[i][j];
                }else{
                    int del1=dp[i][j+1]+s1.charAt(i);
                    int del2=dp[i+1][j]+s2.charAt(j);
                    dp[i+1][j+1]= Math.min(del1,del2);
                }
            }
        }
        return dp[s1.length()][s2.length()];
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值