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

本文主要是介绍代码随想录算法训练营Day55 | 583.两个字符串的删除操作、72.编辑距离,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

最开始想到的是基于最长公共子序列的写法:删除公共子序列以外的字符,两个字符串就相同了

int minDistance0(string word1, string word2) {int n = word1.size();int m = word2.size();vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m; ++j) {if (word1[i - 1] == word2[j - 1])dp[i][j] = dp[i - 1][j - 1] + 1;elsedp[i][j] = std::max(dp[i][j - 1], dp[i - 1][j]); }}// 删除最长公共子序列以外的字符return n + m - 2 * dp[n][m];
}

 另一种基于题意定义DP数组的写法:

题目求需要进行删除的最小操作数,那么就将DP数组定义为目前的最小删除次数

1、DP数组定义: dp[i][j] 表示以word2[j - 1] 为结尾的子串和 word1[i - 1] 为结尾的子串达到相同需要的最小删除操作次数

2、DP数组初始化:dp[0][0]初始化为0,其余首列与首行元素初始化为i / j(有 i / j 个字符的字符串与一个空字符串达到相同需要进行 i / j 次删除操作)

3、递推公式

        · 当word1[i - 1] == word2[j - 1]时,不需要进行删除操作:

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

        · 当word1[i - 1] != word2[j - 1]时,dp[i][j]可以由三个方向取最小转移得到:

                方向1——dp[i][j - 1],在此基础上删除 word1[i - 1]

                方向2——dp[i - 1][j],在此基础上删除 word2[j - 1]

                方向3——dp[i - 1][j - 1],在此基础上删除 word1[i - 1] 和 word2[j - 1]

            最后的递推公式:dp[i][j] = min(dp[i - 1][j - 1] + 2, min(dp[i][j - 1] + 1, dp[i - 1][j] + 1))

4、遍历顺序:i 依赖 i - 1,j 依赖 j - 1,所以从左向右从上向下遍历

int minDistance(string word1, string word2) {// dp[i][j]表示达到相同需要的最小删除操作次数vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1, 0));// 除dp[0][0]外,dp[i][0]和dp[0][j]初始化为i/jfor (int i = 1; i <= word1.size(); ++i)dp[i][0] = i;for (int j = 1; 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];// 三个方向取最小值elsedp[i][j] = std::min(dp[i - 1][j - 1] + 2, std::min(dp[i][j - 1] + 1, dp[i - 1][j] + 1));}}return dp[word1.size()][word2.size()];
}

72.编辑距离

这题仍然是根据题意定义DP数组,重点是理清楚删除、替换、插入三种操作的状态转移

1、DP数组定义: dp[i][j] 表示以 word1[i - 1] 为结尾的子串想要达到与 word2[j - 1] 为结尾的子串相同,需要的最小编辑次数

2、DP数组初始化:dp[0][0]初始化为0,其余首列与首行元素初始化为i / j(有 i / j 个字符的字符串与一个空字符串达到相同需要进行 i / j 次删除操作)

3、递推公式

        · 当word1[i - 1] == word2[j - 1]时,不需要进行编辑操作:

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

        · 当word1[i - 1] != word2[j - 1]时,dp[i][j]可以由三种操作取最小转移得到:

                删除 —— 将word[i - 1]删除,在 dp[i - 1][j] 的基础上+1,

                替换 —— 将 word1[i - 1] 替换为 word2[j - 1],在 dp[i - 1][i - 1] 的基础上+1

                插入 —— 将一个等于 word2[j - 1] 的值插在原先word1[i - 1]的位置上,在 dp[i][j - 1] 的基础上+1

            最后的递推公式:dp[i][j] = min(dp[i - 1][j] + 1, min(dp[i - 1][j - 1] + 1, dp[i][j - 1] + 1))

4、遍历顺序:i 依赖 i - 1,j 依赖 j - 1,所以从左向右从上向下遍历

int minDistance(string word1, string word2) {// dp[i][j]表示达到相同需要的最小编辑操作次数vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1, 0));for (int i = 1; i <= word1.size(); ++i)dp[i][0] = i;for (int j = 1; 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 - 1][j] + 1		(在dp[i - 1][j] + 1的基础上删除word[i - 1])// 替换:dp[i - 1][j - 1] + 1	(在dp[i - 1][i - 1]的基础上将word1[i - 1]替换为word2[j - 1])// 插入:dp[i][j - 1] + 1		(在dp[i][j - 1]的基础上插入一个等于word2[j - 1]的值)dp[i][j] = std::min(dp[i - 1][j] + 1, std::min(dp[i - 1][j - 1] + 1, dp[i][j - 1] + 1));}}}return dp[word1.size()][word2.size()];
}

编辑距离总结

这类题目做多了还是能找到些套路的:

1、DP数组定义

        · DP数组的定义一般是题目要求什么就定义成什么,

        · dp[i][j] 一般表示的是以 word1[i - 1] 为结尾的子串和 word2[j - 1] 为结尾的子串

2、DP数组初始化:结合题意,一般首行和首列的初始化最为重要

3、递推公式

        分析状态转移可以分为“基础”“新增”两部分:

        · 基础:继承之前的状态,如果当前值匹配一般只要进行这步操作

        · 新增:在之前状态的基础上增加操作时新增的值,如果当前值不匹配一般需要额外进行这步操作

4、遍历顺序:结合题意,一般是 i 依赖 i - 1,j 依赖 j - 1,所以大部分情况是从左向右从上向下遍历

这篇关于代码随想录算法训练营Day55 | 583.两个字符串的删除操作、72.编辑距离的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/798813

相关文章

Python实现MQTT通信的示例代码

《Python实现MQTT通信的示例代码》本文主要介绍了Python实现MQTT通信的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 安装paho-mqtt库‌2. 搭建MQTT代理服务器(Broker)‌‌3. pytho

MySQL字符串常用函数详解

《MySQL字符串常用函数详解》本文给大家介绍MySQL字符串常用函数,本文结合实例代码给大家介绍的非常详细,对大家学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql字符串常用函数一、获取二、大小写转换三、拼接四、截取五、比较、反转、替换六、去空白、填充MySQL字符串常用函数一、

MySQL进行数据库审计的详细步骤和示例代码

《MySQL进行数据库审计的详细步骤和示例代码》数据库审计通过触发器、内置功能及第三方工具记录和监控数据库活动,确保安全、完整与合规,Java代码实现自动化日志记录,整合分析系统提升监控效率,本文给大... 目录一、数据库审计的基本概念二、使用触发器进行数据库审计1. 创建审计表2. 创建触发器三、Java

MySQL逻辑删除与唯一索引冲突解决方案

《MySQL逻辑删除与唯一索引冲突解决方案》本文探讨MySQL逻辑删除与唯一索引冲突问题,提出四种解决方案:复合索引+时间戳、修改唯一字段、历史表、业务层校验,推荐方案1和方案3,适用于不同场景,感兴... 目录问题背景问题复现解决方案解决方案1.复合唯一索引 + 时间戳删除字段解决方案2:删除后修改唯一字

Ubuntu 24.04启用root图形登录的操作流程

《Ubuntu24.04启用root图形登录的操作流程》Ubuntu默认禁用root账户的图形与SSH登录,这是为了安全,但在某些场景你可能需要直接用root登录GNOME桌面,本文以Ubuntu2... 目录一、前言二、准备工作三、设置 root 密码四、启用图形界面 root 登录1. 修改 GDM 配

JSONArray在Java中的应用操作实例

《JSONArray在Java中的应用操作实例》JSONArray是org.json库用于处理JSON数组的类,可将Java对象(Map/List)转换为JSON格式,提供增删改查等操作,适用于前后端... 目录1. jsONArray定义与功能1.1 JSONArray概念阐释1.1.1 什么是JSONA

使用Python删除Excel中的行列和单元格示例详解

《使用Python删除Excel中的行列和单元格示例详解》在处理Excel数据时,删除不需要的行、列或单元格是一项常见且必要的操作,本文将使用Python脚本实现对Excel表格的高效自动化处理,感兴... 目录开发环境准备使用 python 删除 Excphpel 表格中的行删除特定行删除空白行删除含指定

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录

Python中反转字符串的常见方法小结

《Python中反转字符串的常见方法小结》在Python中,字符串对象没有内置的反转方法,然而,在实际开发中,我们经常会遇到需要反转字符串的场景,比如处理回文字符串、文本加密等,因此,掌握如何在Pyt... 目录python中反转字符串的方法技术背景实现步骤1. 使用切片2. 使用 reversed() 函

Java操作Word文档的全面指南

《Java操作Word文档的全面指南》在Java开发中,操作Word文档是常见的业务需求,广泛应用于合同生成、报表输出、通知发布、法律文书生成、病历模板填写等场景,本文将全面介绍Java操作Word文... 目录简介段落页头与页脚页码表格图片批注文本框目录图表简介Word编程最重要的类是org.apach