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

本文讲述了在解决两个字符串的删除操作和编辑距离问题时,如何运用动态规划方法,定义dp数组并推导递推公式,特别关注了不相等情况下不同操作(删除和替换)的处理。作者在学习过程中逐步深入理解了问题的本质和解决方案策略。
摘要由CSDN通过智能技术生成

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

两个字符串的删除操作

583. 两个字符串的删除操作
文章讲解:https://programmercarl.com/0583.%E4%B8%A4%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E5%88%A0%E9%99%A4%E6%93%8D%E4%BD%9C.html
题目链接:https://leetcode.cn/problems/delete-operation-for-two-strings/
视频讲解:https://www.bilibili.com/video/BV1we4y157wB/

自己看到题目的第一想法

  • dp数组下标和定义:
    • dp[i][j]:i-1位置的word1下,j-1位置下的word2下相同所需的最小步数(删除多少元素)。
  • 推导公式:
    • 相等的情况下,不需要删除,和前面2位i-1 j-1的值一样大
      • word1[i - 1] == word2[j - 1],dp[i][j] = dp[i-1][j-1]
    • 不相等的情况下,需要删除,可以删除i也可以删除j,删除i时最小值要加1 删除j最小值也要加一
      • word1[i - 1] != word2[j - 1],dp[i][j] = Math.min(dp[i-1][j] + 1,dp[i][j-1] + 1)
  • 初始化值:因为是取的坐上和左边上边,因此要求出dp[i][0]和dp[0][j]的值
    • dp[i][0]的值直接取i的值,dp[0][j]的值直接取j的值。
    • for(int i = 0; i <= charWord1.length; i++) dp[i][0] = i;
    • for(int j = 0; j <= charWord2.length; j++) dp[0][j] = j;
  • 遍历顺序:因为是从小到大,因此从0开始遍历
public int minDistance(String word1, String word2) {
    // dp数组下标和定义
    // dp[i][j]:i-1位置的word1下,j-1位置下的word2下相同所需的最小步数(删除多少元素)。
    // 推导公式
    // 相等的情况下,不需要删除,和前面2位i-1 j-1的值一样大
    // word1[i - 1] == word2[j - 1],dp[i][j] = dp[i-1][j-1]
    // 不相等的情况下,需要删除,可以删除i也可以删除j,删除i时最小值要加1 删除j最小值也要加一
    // word1[i - 1] != word2[j - 1],dp[i][j] = Math.min(dp[i-1][j] + 1,dp[i][j-1] + 1)
    char[] charWord1 = word1.toCharArray();
    char[] charWord2 = word2.toCharArray();
    int[][] dp = new int[charWord1.length + 1][charWord2.length + 1];
    for(int i = 0; i <= charWord1.length; i++){
        dp[i][0] = i;
    }
    for(int j = 0; j <= charWord2.length; j++){
        dp[0][j] = j;
    }
    for(int i = 1; i <= charWord1.length; i++){
        for(int j = 1; j <= charWord2.length; j++){
            if(charWord1[i - 1] == charWord2[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[charWord1.length][charWord2.length];
}

看完代码随想录之后的想法

不想等的时候有3种情况,我只考虑到了2种情况。
三种情况:
情况一:删word1[i - 1],最少操作次数为dp[i - 1][j] + 1

情况二:删word2[j - 1],最少操作次数为dp[i][j - 1] + 1

情况三:同时删word1[i - 1]和word2[j - 1],操作的最少次数为dp[i - 1][j - 1] + 2。
递推公式:dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1});
又因为 dp[i][j - 1] + 1 = dp[i - 1][j - 1] + 2 。所以递推公式dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);

自己实现过程中遇到哪些困难

ac

编辑距离

72. 编辑距离
文章讲解:https://programmercarl.com/0072.%E7%BC%96%E8%BE%91%E8%B7%9D%E7%A6%BB.html
题目链接:https://leetcode.cn/problems/edit-distance/
视频讲解:https://www.bilibili.com/video/BV1qv4y1q78f/

自己看到题目的第一想法

动态规划
确定dp数组以及下标定义
dp[i][j]:i-1位置的word1下j-1的位置的word2下的word1转成word2所使用的最小操作数。
不能纬数组分3种情况,只能二维数组分3种情况,每次判断长度,长的话删除,短的话插入,相同的话更换
确定递推公式
这里就推导不出来了

看完代码随想录之后的想法

  1. dp数组定义和自己看到题目时的想法一致:dp[i][j]:i-1位置的word1下j-1的位置的word2下的word1转成word2所使用的最小操作数。
  2. 递推公式:
    分两种情况,word1[i-1] == word2[j-1]以及 word1[i-1] != word2[j-1]。
    相等时:dp[i][j] = dp[i-1][j-1]。
    不相等时:
    分三种情况:插入一个字符;删除一个字符;替换一个字符。
    因为插入和删除所需的操作是一样的,因此上述三种情况只考虑删除和替换就可以了。
    删除的情况分2种,删word1和删word2。dp[i][j] = dp[i-1][j] + 1和dp[i][j-1] + 1。
    替换的情况只分一种,因为替换要把word1的位置转换成word2,dp[i][j] = dp[i-1][j] + 1。
  3. 初始化值,因为递推左上角往右边推,因此dp[i][0] = i;dp[0][j] = j;

自己实现过程中遇到哪些困难

删除的逻辑自己能理解并写出来,替换的逻辑没理解对,还要看一下替换的逻辑。
替换逻辑:替换元素,word1替换word1[i - 1],使其与word2[j - 1]相同,此时不用增删加元素。回顾一下,if (word1[i - 1] == word2[j - 1])的时候我们的操作 是 dp[i][j] = dp[i - 1][j - 1] 。那么只需要一次替换的操作,就可以让 word1[i - 1] 和 word2[j - 1] 相同。所以 dp[i][j] = dp[i - 1][j - 1] + 1;

public int minDistance(String word1, String word2) {
   char[] charWord1 = word1.toCharArray();
    char[] charWord2 = word2.toCharArray();
    int[][] dp = new int[charWord1.length + 1][charWord2.length + 1];
    for(int i = 0; i <= charWord1.length; i++){
        dp[i][0] = i;
    }
    for(int j = 0; j <= charWord2.length; j++){
        dp[0][j] = j;
    }
    for(int i = 1; i <= charWord1.length; i++){
        for(int j = 1; j <= charWord2.length; j++){
            if(charWord1[i - 1] == charWord2[j - 1]){
                // 相等时,只用取前一个节点的值
                dp[i][j] = dp[i-1][j-1];
            }else{
                // 不相等时分2种情况,删和替换
                // 删
                dp[i][j] = Math.min(dp[i-1][j] + 1,dp[i][j-1] + 1);
                // 替换
                dp[i][j] = Math.min(dp[i][j],dp[i - 1][j - 1] + 1);
            }
        }
    }
    return dp[charWord1.length][charWord2.length];
}

今日收获&学习时长

距离问题的核心就是定义成i-1,j-1时的位置的最xx值。然后再按照i-1和j-1是否来相等来处理递推逻辑,所有的距离问题都是这样处理的,无非是相等、不等时又分不同的子情况,整体还是都一样的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值