力扣算法学习day39-2

力扣算法学习day39-2

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

代码实现-完全版-补上上午的dp解法2

class Solution {
    // 方法一:dp,求两个字符串的最长公共子序列的长度,然后两个分别长度减去它相加即为答案。速度:4ms
    // public int minDistance(String word1, String word2) {
    //     char[] char1 = word1.toCharArray();
    //     char[] char2 = word2.toCharArray();

    //     int[][] dp = new int[char1.length+1][char2.length+1];

    //     for(int i = 1;i < dp.length;i++){
    //         for(int j = 1;j < dp[i].length;j++){
    //             if(char1[i-1] == char2[j-1]){
    //                 dp[i][j] = dp[i-1][j-1] + 1;
    //             } else{
    //                 dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
    //             }
    //         }
    //     }

    //     int length = dp[char1.length][char2.length];
    //     int result = char1.length + char2.length - 2 * length;
    //     return result;
    // }

    // 方法二:dp,通过减去的思路来求 速度 4ms
    public int minDistance(String word1, String word2) {
        char[] char1 = word1.toCharArray();
        char[] char2 = word2.toCharArray();
        // 思路:dp[i][j]:为i-1结尾char1子字符串和j-1结尾的char2子字符串的相同需要的最小步数。
        // 1.char1[i-1] == char2[j-1]:当前元素相同,不需要删除,那么删除情况取i-2结尾char1子字符串
        //                            和j-2结尾char2子字符串的删除情况即可。
        // 迭代公式:dp[i][j] = dp[i-1][j-1];
        // 2.char1[i-1] != char2[j-1]:说明需要删除元素有三种种情况如下
        // (1) 删除char1[i-1]:取dp[i-1][j] + 1(删除的这个元素).
        // (2) 删除char2[j-1]:取dp[i][j-1] + 1(删除的这个元素).
        // (3) 两个都删除,但是可以分析得出,这种情况实际上是被上两种包含了。
        // 故迭代公式为取它们是最小情况:dp[i][j] = Math.min(dp[i-1][j] + 1,dp[i][j-1] + 1);
        int[][] dp = new int[char1.length+1][char2.length+1];

        // 初始化
        // 1.dp[i][0]: 需要以i-1结尾的char1子字符串删除所有才能和空字符串相同所以dp[i][0] = i;
        // 2.dp[0][j]: 同理可得dp[0][j] = j;  注:这里dp[0][0]其实就不需要删除,被两种情况都包含。
        for(int i = 0;i < dp.length;i++){
            dp[i][0] = i;
        }

        for(int j = 0;j < dp[0].length;j++){
            dp[0][j] = j;
        }

        for(int i = 1;i < dp.length;i++){
            for(int j = 1;j < dp[i].length;j++){
                if(char1[i-1] == char2[j-1]){
                    dp[i][j] = dp[i-1][j-1];
                } else{
                    dp[i][j] = Math.min(dp[i-1][j] + 1,dp[i][j-1] + 1);
                }
            }
        }

        return dp[char1.length][char2.length];
    }
}

72-编辑距离

题目

代码实现

class Solution {
    public int minDistance(String word1, String word2) {
        char[] char1 = word1.toCharArray();
        char[] char2 = word2.toCharArray();

        // dp:速度 3-4ms(提交了两次)
        // 1.解法分析:首先这道题是连个字符串的问题,所求的东西是一个最小的值,不需要具体的情况输出,所以
        //   不考虑回溯,那么多半是dp思路,而两个字符串的问题,且两个字符串的长度小于10的2次方,那多考虑
        //   多半是二维dp数组来解决。
        // 2.题目分析:本题类似于删除情况的拓展,即583问题的拓展,在583的情况还要考虑替换,插入这两种情况。

        // 3.定义:dp[i][j]:不妨还是定义为以i-1结尾的char1子字符串和j-1结尾的子字符串变为相同需要最好操作数。
        // 注意:这里操作数有插入、删除、替换三种情况。

        // 4.迭代公式确定:
        // (1)如果char1[i-1] == char2[j-1]:说明当前这两个字符是相同的,所以直接等于以i-2结尾的char1子字符串和
        //    以j-2结尾的char2结尾的子字符串的最小操作数即可,即:dp[i][j] = dp[i-1][j-1];
        //
        // (2)如果char1[i-1] != char2[j-1],说明当前这两个字符不相同,所以需要操作,那么首先有三种操作可以使用。
        // 删除操作:删除char1[i-1],相当于取i-2结尾的char1子字符串和j-1结尾的子字符串的最小操作情况+1(加上这个删除操作)。
        //          即:dp[i-1][j]+1.
        //
        // 插入操作:插入新元素,新元素等于char2的第j-1个元素。这里插入需要理解,char1插入新元素,其实与char2删除j-1这个
        //          元素等效,比如 char1为 a ,char2为ab,那么对于char1的操作为插入b,对于char2的操作为删除b,所以一样
        //          所以,插入插入操作可以转换成char2删除j-1元素。同理,可得:dp[i][j-1]+1.
        //
        // 替换操作:替换操作相当于i-2结尾的char1和j-2结尾的char2子字符串的最小操作情况加上1,即加上将char1中第i-1个元素
        //          替换成char2中第j-1个元素这个替换操作。即dp[i-1][j-1]+1
        //
        // 最终迭代公式(在三种情况中取最小):dp[i][j] = Math.min(Math.min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1]) + 1;

        int[][] dp = new int[char1.length+1][char2.length+1];

        // 初始化
        // 1.dp[i][0]: 需要以i-1结尾的char1子字符串删除所有才能和空字符串相同所以dp[i][0] = i;
        // 2.dp[0][j]: 同理可得dp[0][j] = j;
        for(int i = 0;i < dp.length;i++){
            dp[i][0] = i;
        }

        for(int j = 0;j < dp[0].length;j++){
            dp[0][j] = j;
        }

        for(int i = 1;i < dp.length;i++){
            for(int j = 1;j < dp[i].length;j++){
                if(char1[i-1] == char2[j-1]){
                    dp[i][j] = dp[i-1][j-1];
                } else{
                    dp[i][j] = Math.min(Math.min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1]) + 1;
                }
            }
        }

        return dp[char1.length][char2.length];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人山人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值