Day56|leetcoode 583. 两个字符串的删除操作、72. 编辑距离

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

题目链接:583. 两个字符串的删除操作 - 力扣(LeetCode)

视频链接:动态规划之子序列,还是为了编辑距离做铺垫 | LeetCode:583.两个字符串的删除操作_哔哩哔哩_bilibili

题目概述


给定两个单词word1 word2 ,返回使得word1word2 相同所需的最小步数

每步 可以删除任意一个字符串中的一个字符。

 

示例 1:

输入: word1 = "sea", word2 = "eat"
输出: 2
解释: 第一步将 "sea" 变为 "ea" ,第二步将 "eat "变为 "ea"

示例  2:

输入:word1 = "leetcode", word2 = "etco"
输出:4

思路

1.确定dp数组含义

dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数

2.确定递推公式

1)word1[i - 1] 等于 word2[j - 1]:

dp[i][j] = dp[i - 1][j - 1]

2)word1[i - 1] 不等于 word2[j - 1]:

dp[i - 1][j] + 1(删除word1)

dp[i][j - 1] + 1(删除word2)

dp[i - 1][j - 1] + 2(删除word1和word2)

所以dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1})

3.数组初始化

dp[i][0] = i(word2为空字符串,以i-1为结尾的字符串word1要删除i个元素,才能和word2相同)

dp[0][j] = j(word1为空字符串,以j-1为结尾的字符串word2要删除j个元素,才能和word1相同)

4.确定遍历顺序

dp[i][j]可以由左边、上边、左上方推导而来,所以遍历顺序是从左到右、从上到下。

5.打印dp数组

Day56|leetcoode 583. 两个字符串的删除操作、72. 编辑距离_第1张图片

代码实现(方法一)

class Solution {
public:
    int minDistance(string word1, string word2) {
        vector> dp(word1.size() + 1,vector(word2.size() + 1));
        for(int i = 0;i <= word1.size();i++) dp[i][0] = i;
        for(int j = 0;j <= word2.size();j++) dp[0][j] = j;

        for(int i = 1;i <= word1.size();i++) {
            for(int j = 1;j <= word2.size();j++) {
                if(word1[i - 1] == word2[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1];
                }
                else {
                    dp[i][j] = min({dp[i][j - 1] + 1,dp[i - 1][j] + 1,dp[i - 1][j - 1] + 2});
                }
            }
        }
        return dp[word1.size()][word2.size()];

    }
};

第二种方法:

可以把两个字符串的最长公共子序列求出来,然后用两个字符串加一起的长度 减去 最长公共子序列的长度*2 就可以了。

代码实现(方法二)

class Solution {
public:
    int minDistance(string word1, string word2) {
        vector> dp(word1.size()+1, vector(word2.size()+1, 0));
        for (int i=1; i<=word1.size(); i++){
            for (int j=1; j<=word2.size(); j++){
                if (word1[i-1] == word2[j-1]) dp[i][j] = dp[i-1][j-1] + 1;
                else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
            }
        }
        return word1.size()+word2.size()-dp[word1.size()][word2.size()]*2;
    }
};


leetcode 72. 编辑距离

题目链接:72. 编辑距离 - 力扣(LeetCode)

视频链接:动态规划之子序列,还是为了编辑距离做铺垫 | LeetCode:583.两个字符串的删除操作_哔哩哔哩_bilibili

编辑距离是用动规来解决的经典题目,前面的几道题都是为了这道题做铺垫!

题目概述

 

给你两个单词word1word2 , 请返回将 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')

思路

1. 确定dp数组的含义

dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。

2.确定递推公式

当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] + 1word1删除一个元素

 dp[i][j] = dp[i][j - 1] + 1word2删除一个元素)

(word2添加一个元素,相当于word1删除一个元素,例如 word1 = "ab",word2 = "a"word1删除元素'b'word2添加一个元素'b',变成word1="a", word2="ab" 最终的操作数是一样的)

dp[i][j] = dp[i - 1][j - 1] + 1;替换元素

所以dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1;

3.数组初始化

dp[0][j] = j

dp[i][0] = i

4.确定遍历顺序

Day56|leetcoode 583. 两个字符串的删除操作、72. 编辑距离_第2张图片

由上图可以看出:dp[i][j]可以由 左边、上边、左上方推出,所以遍历顺序为从左到右,从上到下。

5.打印dp数组(以输入:word1 = "horse", word2 = "ros"为例)

Day56|leetcoode 583. 两个字符串的删除操作、72. 编辑距离_第3张图片

代码实现

lass Solution {
public:
    int minDistance(string word1, string word2) {
        vector> dp(word1.size() + 1,vector(word2.size() + 1,0));
        for(int i = 0;i <= word1.size();i++) dp[i][0] = i;
        for(int j = 0;j <= word2.size();j++) dp[0][j] = j;

        for(int i = 1;i <= word1.size();i++) {
            for(int j = 1;j <= word2.size();j++) {
                if(word1[i - 1] == word2[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1];
                }
                else {
                    dp[i][j] = min({dp[i - 1][j] + 1,dp[i][j - 1] + 1,dp[i - 1][j - 1] + 1});
                }
            }
        }
        return dp[word1.size()][word2.size()];

    }
};

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