【算法与数据结构】583、72、LeetCode两个字符串的删除操作+编辑距离

news2024/11/18 20:02:01

文章目录

  • 一、583、两个字符串的删除操作
  • 二、72、编辑距离
  • 三、完整代码

所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。

一、583、两个字符串的删除操作

在这里插入图片描述

  思路分析:本题的思路和115、不同的子序列差不多,只是变成了两个字符串都能删除字符。

  1. 第一步,动态数组的含义。 d p [ i ] [ j ] dp[i][j] dp[i][j]代表使得 w o r d 1 [ 0 , i − 1 ] word1[0, i-1] word1[0,i1] w r o d 2 [ 0 , j − 1 ] wrod2[0, j-1] wrod2[0,j1]相等所需删除的最小步数。
  2. 第二步,递推公式。 d p [ i ] [ j ] dp[i][j] dp[i][j]可以由两种情况推导出来:
  • w o r d 1 [ i − 1 ] word1[i - 1] word1[i1] w o r d 2 [ j − 1 ] word2[j - 1] word2[j1]相同:那么最小步数和使得 w o r d 1 [ 0 , i − 2 ] word1[0, i-2] word1[0,i2] w r o d 2 [ 0 , j − 2 ] wrod2[0, j-2] wrod2[0,j2]相等所需删除的最小步数相同。 d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] dp[i][j] = dp[i-1][j-1] dp[i][j]=dp[i1][j1]
  • w o r d 1 [ i − 1 ] word1[i - 1] word1[i1] w o r d 2 [ j − 1 ] word2[j - 1] word2[j1]不相同:这种情况的 d p [ i ] [ j ] dp[i][j] dp[i][j]可以由三部分构成:若 w o r d 1 [ 0 , i − 2 ] word1[0, i - 2] word1[0,i2] w o r d 2 [ 0 , j − 1 ] word2[0, j - 1] word2[0,j1]做了 d p [ i − 1 ] [ j ] dp[i - 1][j] dp[i1][j]次删除操作以后会相等,那么再删除 w o r d 1 [ i − 1 ] word1[i - 1] word1[i1]以后又可以相等,即 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + 1 dp[i][j] = dp[i - 1][j] + 1 dp[i][j]=dp[i1][j]+1;若 w o r d 1 [ 0 , i − 1 ] word1[0, i - 1] word1[0,i1] w o r d 2 [ 0 , j − 2 ] word2[0, j - 2] word2[0,j2]做了 d p [ i ] [ j − 1 ] dp[i][j - 1] dp[i][j1]次删除操作以后会相等,那么再删除 w o r d 2 [ j − 1 ] word2[j - 1] word2[j1]以后又可以相等,即 d p [ i ] [ j ] = d p [ i ] [ j − 1 ] + 1 dp[i][j] = dp[i][j - 1] + 1 dp[i][j]=dp[i][j1]+1。因为要求最小步数,那么我们对两项取最小: d p [ i ] [ j ] = m i n ( d p [ i − 1 ] [ j ] + 1 , d p [ i ] [ j − 1 ] + 1 ) dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1) dp[i][j]=min(dp[i1][j]+1,dp[i][j1]+1)
	if (word1[i - 1] == word2[j - 1]) dp[i][j] = dp[i - 1][j - 1];
	else dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + 1;
  1. 第三步,元素初始化。 d p [ i ] [ 0 ] dp[i][0] dp[i][0](第一列)表示字符串 w o r d 1 [ 0 , i − 1 ] word1[0, i-1] word1[0,i1]变成空字符串需要删除的最小字符个数。 d p [ 0 ] [ j ] dp[0][j] dp[0][j](第一行)表示 w o r d 2 [ 0 , j − 1 ] word2[0, j-1] word2[0,j1]变成空字符串需要删除的最小字符个数。其中,空字符串word1变成空字符串word2的个数为0。那么 d p [ 0 ] [ 0 ] = 0 , d p [ i ] [ 0 ] = i , d p [ 0 ] [ j ] = j dp[0][0]=0, dp[i][0] = i, dp[0][j] = j dp[0][0]=0,dp[i][0]=i,dp[0][j]=j
		for (int i = 1; i <= word1.size(); i++) dp[i][0] = i;		// 第一列初始化为i
		for (int j = 1; j <= word2.size(); j++) dp[0][j] = j;		// 第一行初始化为i
  1. 第四步,递归顺序。一共有两层循环,从前往后进行遍历。
  2. 第五步,打印结果。

在这里插入图片描述

  程序如下

// 583、两个字符串的删除操作-动态规划
class Solution {
public:
	int minDistance(string word1, string word2) {
		vector<vector<uint64_t>> dp(word1.size() + 1, vector<uint64_t>(word2.size() + 1, 0));	// dp[0][0]为0
		for (int i = 1; i <= word1.size(); i++) dp[i][0] = i;		// 第一列初始化为i
		for (int j = 1; j <= word2.size(); j++) dp[0][j] = j;		// 第一行初始化为i
		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], dp[i][j - 1]) + 1;
			}
		}
		return dp[word1.size()][word2.size()];
	}
};

复杂度分析:

  • 时间复杂度: O ( n ∗ m ) O(n*m) O(nm) n n n m m m分别是两个字符串的长度。
  • 空间复杂度: O ( n ∗ m ) O(n*m) O(nm)

二、72、编辑距离

在这里插入图片描述

  思路分析:本题在583题的基础之上加入了插入和替换操作。我们同样用动态规划的方法分析。

  1. 第一步,动态数组的含义。 d p [ i ] [ j ] dp[i][j] dp[i][j]代表使得 w o r d 1 [ 0 , i − 1 ] word1[0, i-1] word1[0,i1] w r o d 2 [ 0 , j − 1 ] wrod2[0, j-1] wrod2[0,j1]相等所需的最小操作数。
  2. 第二步,递推公式。 d p [ i ] [ j ] dp[i][j] dp[i][j]可以由两种情况推导出来:
  • w o r d 1 [ i − 1 ] word1[i - 1] word1[i1] w o r d 2 [ j − 1 ] word2[j - 1] word2[j1]相同:那么最小操作数和使得 w o r d 1 [ 0 , i − 2 ] word1[0, i-2] word1[0,i2] w r o d 2 [ 0 , j − 2 ] wrod2[0, j-2] wrod2[0,j2]相等所需的最小操作数相同。 d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] dp[i][j] = dp[i-1][j-1] dp[i][j]=dp[i1][j1]
  • w o r d 1 [ i − 1 ] word1[i - 1] word1[i1] w o r d 2 [ j − 1 ] word2[j - 1] word2[j1]不相同:这种情况的 d p [ i ] [ j ] dp[i][j] dp[i][j]可以由三部分构成:增加、删除和替换。删除部分和583题一致: d p [ i ] [ j ] = m i n ( d p [ i − 1 ] [ j ] + 1 , d p [ i ] [ j − 1 ] + 1 ) dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1) dp[i][j]=min(dp[i1][j]+1,dp[i][j1]+1)。而增加字符和删除的操作数没有区别。若 w o r d 1 [ 0 , i − 2 ] word1[0, i - 2] word1[0,i2] w o r d 2 [ 0 , j − 2 ] word2[0, j - 2] word2[0,j2]做了 d p [ i − 1 ] [ j − 1 ] dp[i - 1][j - 1] dp[i1][j1]次删除操作以后会相等,那么再替换 w o r d 1 [ i − 1 ] word1[i - 1] word1[i1]或者 w o r d 2 [ j − 1 ] word2[j - 1] word2[j1]之间任意一个元素以后又可以相等,即 d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + 1 dp[i][j] = dp[i - 1][j - 1] + 1 dp[i][j]=dp[i1][j1]+1。因为要求最小操作数,那么我们对两项取最小: d p [ i ] [ j ] = m i n ( d p [ i − 1 ] [ j ] + 1 , d p [ i ] [ j − 1 ] + 1 , d p [ i − 1 ] [ j − 1 ] + 1 ) = m i n ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] , d p [ i − 1 ] [ j − 1 ] ) + 1 dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + 1) = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1 dp[i][j]=min(dp[i1][j]+1,dp[i][j1]+1,dp[i1][j1]+1)=min(dp[i1][j],dp[i][j1],dp[i1][j1])+1
	if (word1[i - 1] == word2[j - 1]) dp[i][j] = dp[i - 1][j - 1];
	//else dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;	// min()函数只接受两个参数,或者数组
	else dp[i][j] = min({ dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1] }) + 1;
  1. 第三步,元素初始化。 d p [ i ] [ 0 ] dp[i][0] dp[i][0](第一列)表示字符串 w o r d 1 [ 0 , i − 1 ] word1[0, i-1] word1[0,i1]变成空字符串需要的最少操作数。 d p [ 0 ] [ j ] dp[0][j] dp[0][j](第一行)表示 w o r d 2 [ 0 , j − 1 ] word2[0, j-1] word2[0,j1]变成空字符串需要的最少操作数。其中,空字符串word1变成空字符串word2的个数为0。那么 d p [ 0 ] [ 0 ] = 0 , d p [ i ] [ 0 ] = i , d p [ 0 ] [ j ] = j dp[0][0]=0, dp[i][0] = i, dp[0][j] = j dp[0][0]=0,dp[i][0]=i,dp[0][j]=j
	for (int i = 1; i <= word1.size(); i++) dp[i][0] = i;		// 第一列初始化为i
	for (int j = 1; j <= word2.size(); j++) dp[0][j] = j;		// 第一行初始化为i
  1. 第四步,递归顺序。一共有两层循环,从前往后进行遍历。
  2. 第五步,打印结果。

在这里插入图片描述

  程序如下

// 72、编辑距离-动态规划
class Solution2 {
public:
	int minDistance(string word1, string word2) {
		vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1, 0));	// dp[0][0]为0
		for (int i = 1; i <= word1.size(); i++) dp[i][0] = i;		// 第一列初始化为i
		for (int j = 1; j <= word2.size(); j++) dp[0][j] = j;		// 第一行初始化为i
		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(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;	// min()函数只接受两个参数,或者数组
				else dp[i][j] = min({ dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1] }) + 1;
			}
		}
		return dp[word1.size()][word2.size()];
	}
};

复杂度分析:

  • 时间复杂度: O ( n ∗ m ) O(n*m) O(nm) n n n m m m分别是两个字符串的长度。
  • 空间复杂度: O ( n ∗ m ) O(n*m) O(nm)

三、完整代码

# include <iostream>
# include <vector>
# include <string>
using namespace std;

// 583、两个字符串的删除操作-动态规划
class Solution {
public:
	int minDistance(string word1, string word2) {
		vector<vector<uint64_t>> dp(word1.size() + 1, vector<uint64_t>(word2.size() + 1, 0));	// dp[0][0]为0
		for (int i = 1; i <= word1.size(); i++) dp[i][0] = i;		// 第一列初始化为i
		for (int j = 1; j <= word2.size(); j++) dp[0][j] = j;		// 第一行初始化为i
		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], dp[i][j - 1]) + 1;
			}
		}
		return dp[word1.size()][word2.size()];
	}
};

// 72、编辑距离-动态规划
class Solution2 {
public:
	int minDistance(string word1, string word2) {
		vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1, 0));	// dp[0][0]为0
		for (int i = 1; i <= word1.size(); i++) dp[i][0] = i;		// 第一列初始化为i
		for (int j = 1; j <= word2.size(); j++) dp[0][j] = j;		// 第一行初始化为i
		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(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;	// min()函数只接受两个参数,或者数组
				else dp[i][j] = min({ dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1] }) + 1;
			}
		}
		return dp[word1.size()][word2.size()];
	}
};

int main() {
	//string word1 = "sea", word2 = "eat";	// 测试案例
	//Solution s1;
	//int result = s1.minDistance(word1, word2);

	string word1 = "horse", word2 = "ros";	// 测试案例
	Solution2 s1;
	int result = s1.minDistance(word1, word2);

	cout << result << endl;
	system("pause");
	return 0;
}

end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1435183.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【RT-DETR有效改进】可视化热力图 | 支持自定义模型、置信度选择等功能(论文必备)

👑欢迎大家订阅本专栏,一起学习RT-DETR👑 一、本文介绍 本文给大家带来的机制是的是RT-DETR可视化热力图功能,热力图作为我们论文当中的必备一环,可以展示出我们呈现机制的有效性,同时支持视频讲解,本文的内容是根据检测头的输出内容,然后来绘图。 在开始之前…

本地部署TeamCity打包发布GitLab管理的.NET Framework 4.5.2的web项目

本地部署TeamCity 本地部署TeamCity打包发布GitLab管理的.NET Framework 4.5.2的web项目部署环境配置 TeamCity 服务器 URLTeamCity 上 GitLab 的相关配置GitLab 链接配置SSH 配置项目构建配置创建项目配置构建步骤构建触发器结语本地部署TeamCity打包发布GitLab管理的.NET Fra…

【BIAI】Lecture 13 - Language processing

Language processing 专业术语 Aphasia 失语症 fMRI 功能性磁共振成像 auditory cortex 听觉皮层 motor cortex 运动皮层 primary visual cortex 初级视觉皮层 permotor cortex 前运动皮层 课程概要 What is language 语言是一种用词汇按照语法规则组合来表示和交流信息的系统…

【教学类-46-05】吉祥字门贴5.0(华光彩云_CNKI 文本框 空心字涂色 ,繁简都可以,建议简体)

作品展示 背景需求&#xff1a; 1、制作了空心字的第1款 华光通心圆_CNKI &#xff0c;发现它不能识别某些简体字&#xff0c;但可以识别他们的繁体字&#xff08;繁体为准&#xff09; 【教学类-46-01】吉祥字门贴1.0&#xff08;华光通心圆_CNKI 文本框 空心字涂色&#xf…

nginx+flask+Gunicorn反代理服务拿不到真实IP的解决

背景 本人在宝塔linux环境&#xff0c;要部署flask的简单后端并且用Ngnix反代理&#xff0c;用Gunicorn框架部署。&#xff08;o(╥﹏╥)o中间磕磕绊绊总算部署上去了&#xff0c;需要了解Gunicorn怎么部署的朋友&#xff0c;评论区留言&#xff0c;我加补一篇介绍&#xff09;…

CentOS 8 安装配置 Hadoop3.3.6 伪分布式安装方式(适用于开发和调试)

1.配置服务器ssh免密登录&#xff0c;否则后面启动会报错&#xff1a;尝试通过SSH连接到主机出现认证错误的提示 配置服务器ssh免密登录&#xff1a; 1.生成SSH密钥对&#xff08;如果尚未生成&#xff09;&#xff1a; 执行下面的命令生成密钥对&#xff0c;一直回车即可 ssh…

爬虫实战--爬取简单文字图片并保存到mongodb数据库

文章目录 前言发现宝藏 前言 为了巩固所学的知识&#xff0c;作者尝试着开始发布一些学习笔记类的博客&#xff0c;方便日后回顾。当然&#xff0c;如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚&#xff0c;文章中如果有记录错误&#xff0c;欢迎读者朋友们…

七、类与对象

文章目录 类与对象1.1 自定义类1.2 第一个类1.3 private变量1.4 变量默认值1.5 构造方法1.6 类和对象的生命周期 类与对象 本文为书籍《Java编程的逻辑》1和《剑指Java&#xff1a;核心原理与应用实践》2阅读笔记 将客观世界中存在的一切可以描述的事物称为对象&#xff08;实…

浏览器提示ERR_SSL_KEY_USAGE_INCOMPATIBLE解决

ERR_SSL_KEY_USAGE_INCOMPATIBLE报错原因 ERR_SSL_KEY_USAGE_INCOMPATIBLE 错误通常发生在使用 SSL/TLS 连接时,指的是客户端和服务器之间进行安全通信尝试失败,原因是证书中的密钥用途(Key Usage)或扩展密钥用途(Extended Key Usage, EKU)与正在尝试的操作不兼容。这意味…

性能评测|虚拟化和裸金属 K8s 哪个性能更好?

本文重点 整体而言&#xff0c;SKS&#xff08;虚拟机 Kubernetes&#xff09;可以达到裸金属 Kubernetes 性能的 82% – 96%&#xff0c;满足绝大部分场景下生产容器应用的性能需求。更多虚拟化与裸金属 Kubernetes 架构、特性、适用场景与性能对比&#xff0c;欢迎阅读文末电…

【算法】枚举——蓝桥杯、日期统计、特殊日期(位数之和)、2023、特殊日期(倍数)、跑步锻炼

文章目录 蓝桥杯日期统计特殊日期&#xff08;位数之和&#xff09;2023特殊日期&#xff08;倍数&#xff09;跑步锻炼 蓝桥杯 日期统计 日期统计 如果暴力枚举100个数的八次循环那就是1016次运算&#xff0c;时间复杂度太高了&#xff0c;好在前四次的2023是确定的&#xf…

Mybatis中的sql-xml延迟加载机制

Mybatis中的sql-xml延迟加载机制 hi&#xff0c;我是阿昌&#xff0c;今天记录一下关于Mybatis中的sql-xml延迟加载机制 一、前言 首先mybatis技术本身就不多介绍&#xff0c;说延迟加载机制之前&#xff0c;那要先知道2个概念&#xff1a; 主查询对象关联对象 假设咱们现…

人工智能福利站,初识人工智能,图神经网络学习,第二课

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

UML之在Markdown中使用Mermaid绘制类图

1.UML概述 UML&#xff08;Unified modeling language UML&#xff09;统一建模语言&#xff0c;是一种用于软件系统分析和设计的语言工具&#xff0c;它用于帮助软件开发人员进行思考和记录思路。 类图是描述类与类之间的关系的&#xff0c;是UML图中最核心的。类图的是用于…

SpringBoot实战第三天

今天主要完成了&#xff1a; 新增棋子分类 棋子分类列表 获取棋子分类详情 更新棋子分类 更新棋子分类和添加棋子分类_分组校验 新增棋子 新增棋子参数校验 棋子分类列表查询(条件分页) 先给出分类实体类 Data public class Category {private Integer id;//主键IDNot…

mysql 批量查询取每一组最新一条数据

AI回答 需求 根据车牌号查询最新的一条交车记录的‘合同号’ &#xff0c;与上面需要类似&#xff0c;这里只需要查询‘合同号’这个字段 方式1 直接把需要查询的字段加上contract_no&#xff0c;直接查&#xff0c;不用子查询 SELECT number_plate,id,contract_no, MAX( …

❤ React18 环境搭建项目与运行(地址已经放Gitee开源)

❤ React项目搭建与运行 环境介绍 node v20.11.0 react 18.2 react-dom 18.2.0一、React环境搭建 第一种普通cra搭建 1、检查本地环境 node版本 18.17.0 检查node和npm环境 node -v npm -v 2、安装yarn npm install -g yarn yarn --version 3、创建一个新的React项目…

SSRF漏洞给云服务元数据带来的安全威胁

文章目录 前言元数据服务威胁1.1 Metadata元数据1.2 RAM资源管理角色1.3 STS 临时凭据利用1.4 CF云环境利用框架1.5 元数据安全性增强 TerraformGoat2.1 永久性AccessKey2.2 SSRF靶场环境搭建2.3 腾讯云CVM配角色2.4 接管腾讯云控制台 SSRF组合拳案例3.1 上传图片功能SSRF3.2 文…

vue3-内置组件-Transition

基于状态变化的过渡和动画&#xff08;常用&#xff09; 建议多看几遍~~。然后动手去写写&#xff0c;学编程只有多动手才能有感觉。 内置组件: 它在任意别的组件中都可以被使用&#xff0c;无需注册。 Vue 提供了两个内置组件&#xff0c;可以帮助你制作基于状态变化的过渡和动…

Jmeter 01 -概述线程组

1、Jmeter:概述 1.1 是什么&#xff1f; Jmeter是Apache公司使用Java 开发的一款测试工具 1.2 为什么&#xff1f; 高效、功能强大 模拟一些高并发或多次循环等特殊场景 1.3 怎么用&#xff1f; 下载安装 1、下载jmeter&#xff0c;解压缩2、安装Java环境&#xff08;jmet…