代码随想录 11.16 || 动态规划 LeetCode 583.两个字符串的删除操作、72.编辑距离

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

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

解法一:

删除两个字符串中多余的字符,使得两个字符串相同,此时我们定义 dp[i][j] 为以 word1 中的 i - 1 为结尾 和以 word2 中的 j - 1 为结尾的字符串,其最少操作次数为 dp[i][j];

递推公式为,当 word1[i] == word2[j] 相等时,不需要进行任何删除操作,dp[i][j] = dp[i - 1][j - 1];当不满足上述条件时,dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1),因为我们可以在任意字符串中删除字符,所以选取删除操作最少的那个字符串 + 1;

dp 数组初始化,当任意一个字符串为空时,另一个字符串需要做的操作就是删除其所有。按照 i 和 j 初始化 dp[i][0] 和 dp[0][j];

遍历顺序,从二维的角度,自左上向右下;

出问题时,打印 dp 数组 debug。

cpp 复制代码
class Solution {
public:
    int minDistance(string word1, string word2) {
        int len1 = word1.size(), len2 = word2.size();

        auto dp = vector<vector<int>> (len1 + 1, vector<int> (len2 + 1, 0));
        for (int i = 1; i <= len1; ++i) dp[i][0] = i;
        for (int j = 1; j <= len2; ++j) dp[0][j] = j;

        for (int i = 1; i <= len1; ++i) {
            for (int j = 1; j <= len2; ++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);
            }
        }
        
        return dp[len1][len2];
    }
};
解法二:

计算让两个字符串数组变相同的最少操作数,其实就是计算两个字符串之间不同字符的个数,进而将其转化为计算两个字符数组的最大公共子序列。

cpp 复制代码
class Solution { // 最长公共子序列
public:
    int minDistance(string word1, string word2) {
        int len1 = word1.size(), len2 = word2.size();

        auto dp = vector<vector<int>> (len1 + 1, vector<int> (len2 + 1, 0));

        for (int i = 1; i <= len1; ++i) {
            for (int j = 1; j <= len2; ++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 len1 + len2 - 2 * dp[len1][len2];
    }
};

两个字符数组的长度 - 2 * 最长公共子序列 = 不同字符的数量 = 删除需要的步数。

72.编辑距离

给你两个单词 word1 和 word2,请返回将 word1 转换成 word2 所使用的最少操作数。你可以对一个单词进行如下三种操作:插入、删除和替换。72.编辑距离583.两个字符串的删除操作 最大差别在于,本题允许插入、删除和替换操作,而不是仅限于删除。

举例,当 word1 = abc,word2 = ab 时,如何统一两个字符串,可以由 word2 添加字符 c,也可以由 word1 删除字符 c,从此可以看出,添加和删除字符串是相对的,属于同一种情况,操作对象不同。对于替换操作,假设有字符串 abc 和 abd,替换下表为 2 的字符即可,无需考虑操作对象,都是一次操作。

cpp 复制代码
class Solution {
public:
    int minDistance(string word1, string word2) {
        int len1 = word1.size(), len2 = word2.size();

        auto dp = vector<vector<int>> (len1 + 1, vector<int> (len2 + 1, 0));
        for (int i = 0; i <= len1; ++i) dp[i][0] = i;
        for (int j = 0; j <= len2; ++j) dp[0][j] = j;

        for (int i = 1; i <= len1; ++i) {
            for (int j = 1; j <= len2; ++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], min(dp[i - 1][j], dp[i][j - 1])) + 1;
            }
        }

        return dp[len1][len2];
    }
};
相关推荐
车队老哥记录生活1 小时前
【MPC】模型预测控制笔记 (3):无约束输出反馈MPC
笔记·算法
地平线开发者1 小时前
BEV 感知算法评价指标简介
算法·自动驾驶
不过四级不改名6772 小时前
用c语言实现简易c语言扫雷游戏
c语言·算法·游戏
C++ 老炮儿的技术栈3 小时前
手动实现strcpy
c语言·开发语言·c++·算法·visual studio
倔强的石头_4 小时前
【数据结构与算法】利用堆结构高效解决TopK问题
后端·算法
倔强的石头_4 小时前
【数据结构与算法】详解二叉树下:实践篇————通过链式结构深入理解并实现二叉树
后端·算法
哎写bug的程序员4 小时前
leetcode复盘(1)
算法·leetcode·职场和发展
风靡晚4 小时前
用于汽车毫米波雷达的四维高分辨率点云图像
人工智能·算法·机器学习·计算机视觉·汽车·信息与通信·信号处理
简简单单做算法5 小时前
基于FD-MIMO技术的雷达通信一体化系统波形设计matlab模拟与仿真
算法
遥不可及3875 小时前
动态规划(DP)从入门到精通:原理详解与经典问题解析
java·算法