当前位置: 首页 > news >正文

C++ day56 两个字符串的删除操作 编辑距离

题目1:583 两个字符串的删除操作

题目链接:两个字符串的删除操作

对题目的理解

返回使两个单词word1和word2相同的最少删除多少个元素,两个单词至少包含一个字母,且仅包含小写字母

思路1:这道题与昨天的不同子序列很相似,只是有一点不同,不同子序列是使用s字符串去匹配t字符串,而本题可以对word1进行删减得到word2,也可以用word2删减获得word1,经过一系列删除操作,最终两个单词相等就可以了。

思路2:本题其实就是求word1和word2达到最长公共子序列时,使用两个单词的长度之和减去最长公共子序列的长度的2倍。

动态规划(思路1)

动规五部曲

1)dp数组及下标i的含义

dp[i][j]:以i-1结尾的word1和以j-1结尾的word2达到word1和word2相同的最少操作次数

2)递推公式

还是考虑两种情况,当前子串word1结尾的字符与子串word2结尾的字符相等和不等的情况

i)结尾的字符相等,即word1[i-1]==word2[j-1],因为已经相等了,这两个字符就不会改变操作的次数,那么此时就不用考虑这两个字符了,(模拟将这两个字符删除),则当前的结果与这两个字符的前面的字符结尾(word1[i-1],word2[j-1])的结果相同,即dp[i][j] = dp[i-1][j-1]

ii)结尾的字符不等,因为word1[i-1]和word2[j-1]两个字符不等,所以考虑删除元素,这又可以分为3种情况,

 删除word1[i-1] ,也就是不考虑word1[i-1]这个元素了,那么在word1中没有这个元素了,则最终的结果应该是其前一个字符word1[i-2]与word2[j-1]进行比较,看是否相等, 

即 dp[i][j]=dp[i-1][j]+1,因为删除一个元素,所以加1

删除word2[j-1] ,不考虑word2[j-1]这个元素了,那么在word2中就没有这个元素了,则最终的结果应该是word2子串的前一个字符word2[j-2]与word1[i-1]进行比较,看是否相等

即dp[i][j]=dp[i][j-1],因为删除了一个元素,所以加1

删除word1[i-1]和word2[j-1],不考虑word1[i-1]和word2[j-1]这两个元素了,那么在word1和word2中就没有这两个元素了,最终就是word2子串的前一个字符word2[i-2]与word1子串的前一个字符word1[i-2]进行比较 ,即 dp[i][j]=dp[i-1][j-1]+2,因为删除了2个元素,所以加2

dp[i][j] = min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+2)

3)dp数组初始化

根据递推公式,第一行,第一列都要进行初始化,即dp[i][0]   dp[0][j]都需要进行初始化

根据dp数组定义  dp[i][0]代表以i-1结尾的word1和以-1结尾的word2相同的最小操作次数,word2以-1结尾,说明word2是空串,那么要想达到两个子串相等,说明word1需要删除i个元素,需要最少操作i次,所以dp[i][0]=i

同理,dp[0][j]代表以-1结尾的word1和以j-1结尾的word2相同的最小操作次数,word1是空串,此时要想让两个子串相等,word1也需要变为空串,需要将word2中的元素全部删除才可以,即删除j个元素,最少操作j次  ,所以dp[0][j]=j

4)遍历顺序

根据递推公式,从左到右遍历,从上到下遍历

5)打印dp数组

代码,注意定义dp数组的时候,一定要word1.size()+1,一定要加1,因为dp数组的定义是以i-1结尾,最终要遍历到最后一个元素word1.size()-1的时候,才是dp数组的最后一个元素word1.size()减去1为结尾

class Solution {
public:int minDistance(string word1, string word2) {//定义dp数组vector<vector<int>> dp(word1.size()+1,vector<int>(word2.size()+1));//初始化dp数组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,min(dp[i][j-1]+1,dp[i-1][j-1]+2));}}return dp[word1.size()][word2.size()];}
};

上面的代码会出现如下错误

根据出现的错误,将其对应的各个dp数组打印出来,发现dp[0][1]以及dp[1][0]仍是0,并没有初始化成1,所以初始化这里出现了问题

就是因为在初始化的时候,没有将dp[word1.size()][0]和dp[0][word2.size()]初始化

注意初始化数组时,因为是初始化整个dp[i][j],所以将dp[i][0]和dp[0][j]整个进行初始化,所以,i从0到word1.size()都要初始化 ,j从0到word2.size()都要初始化,注意初始化时,一定要使得i<=word1.size(),j<=word2.size(),等号不能丢掉,否则就会在案例出现的时候出现错误

因此,将代码修改如下:

class Solution {
public:int minDistance(string word1, string word2) {//定义dp数组vector<vector<int>> dp(word1.size()+1,vector<int>(word2.size()+1));//初始化dp数组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,min(dp[i][j-1]+1,dp[i-1][j-1]+2));}}return dp[word1.size()][word2.size()];}
};
  • 时间复杂度: O(n * m)
  • 空间复杂度: O(n * m)
流程图

动态规划(思路2)

思路2:本题也可以在求最长公共子序列的基础上进行求解,将word1和word2的最长公共子序列的长度求出来,然后使用word1和word2的长度之和减去2倍的公共子序列的长度,即为所求。

流程

代码

class Solution {
public:int minDistance(string word1, string word2) {//定义并初始化dp数组vector<vector<int>> dp(word1.size()+1,vector<int>(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]);  }}int result = word1.size()+word2.size()-2*dp[word1.size()][word2.size()];return result;}
};
  • 时间复杂度: O(n * m)
  • 空间复杂度: O(n * m)

题目2:72 编辑距离

题目链接:编辑距离

对题目的理解

返回将单词word1转换成word2使用最少的操作数,两个单词的长度大于等于0,且均由小写字母组成,操作包括插入一个字符,删除一个字符以及替换一个字符

动态规划

动规五部曲

1)dp数组及下标i的定义

dp[i][j]:以下标i-1结尾的word1和以下标j-1结尾的word2相同的最少操作次数

2)递推公式

还是分为两种情况,两个元素相等以及两个元素不等的情况

1)两个元素word1[i-1]和word2[j-1]相等,则不考虑这两个元素,因为已经相等了,所以不需要对二者进行操作,只需要考虑前面的word1[i-2]和word2[j-2]就行,dp[i][j]=dp[i-1][j-1]

2)两个元素word1[i-1]和word2[j-1]不相等,则需要对元素进行删减以及替换的操作,所以这又可以分为3种情况

i)只考虑word1[i-1],只对这个元素进行操作,当word1[i-1]不等于word2[j-1]时,将word1[i-1]删除,那么此时对于word1而言,就是以word1[i-2]为结尾的子串与word2[j-1]为结尾的子串的最小操作次数的基础上进行操作(删除)加1,因此,dp[i][j]=dp[i-1][j]+1  加1是因为进行了一个删除操作

ii)只考虑word2[j-1],只对这个元素进行操作,当word1[i-1]不等于word2[j-1]时,将word2[j-1]删除,那么对于word2而言,只剩下以word2[j-2]为结尾的子串与word1[i-1]为结尾的子串的最小操作次数的基础上进行操作(删除)加1,dp[i][j]=dp[i][j-1]+1  加1是因为进行了一个删除操作

注:word2添加一个元素,相当于word1删除一个元素,例如 word1 = "ad" ,word2 = "a"word1删除元素'd' 和 word2添加一个元素'd',变成word1="a", word2="ad", 最终的操作数是一样! 

iii)如果word1[i-1]不等于word2[j-1],要使得这两个位置对应的元素相等(dp[i][j]=dp[i-1][j-1],这个等式是word[i-1]和word[j-1]相等的情况,但是此时是要让这两个元素相等,所以需要考虑这两个元素在原来以word1[i-2]为结尾的子串和以word2[j-2]为结尾的子串相同进行操作的基础上加上一个替换的操作就ok),只需要dp[i][j]=dp[i-1][j-1]+1   加1是因为进行了一次替换操作

dp[i][j]= min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+1)

3)dp数组初始化

根据递推公式,第一行和第一列需要初始化,

根据dp数组的定义,dp[i][0]表示以下标i-1为结尾的word1和以下标-1为结尾的word2相同的最少操作次数,而以下标-1为结尾的word2是一个空串,要想使得这两个串的长度相等,那么word1至少需要操作i次,因为word1中含有i个元素

dp[0][j]表示以下标-1为结尾的word1和以下标j-1为结尾的word2相同的最少操作次数,而以下标01结尾的word1是一个空串,要想使得word1和word2的长度相等,那么word2至少需要操作j次,因为word2中含有j个元素

因此初始化如下

注意for循环中一定要是小于等于,一定要有等于,这样才能确保dp数组中的最后一个边界值,即dp[word1.size()][0]和dp[0][word2.size()]初始化了,如果只写小于的话,这组元素就会被落掉,相当于dp[word1.size()][0]和dp[0][word2.size()]没有进行初始化,默认为0

4)遍历顺序

根据递推公式,从左往右遍历,从上到下遍历

5)打印dp数组

最终的结果在dp[word1.size()][word2.size()]中

代码

class Solution {
public:int minDistance(string word1, string word2) {//定义dp数组vector<vector<int>> dp(word1.size()+1,vector<int>(word2.size()+1));//初始化dp数组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,min(dp[i][j-1]+1,dp[i-1][j-1]+1));}}return dp[word1.size()][word2.size()];}
};
  • 时间复杂度: O(n * m)
  • 空间复杂度: O(n * m)

代码流程

删减元素

添加元素

相关文章:

C++ day56 两个字符串的删除操作 编辑距离

题目1&#xff1a;583 两个字符串的删除操作 题目链接&#xff1a;两个字符串的删除操作 对题目的理解 返回使两个单词word1和word2相同的最少删除多少个元素&#xff0c;两个单词至少包含一个字母&#xff0c;且仅包含小写字母 思路1&#xff1a;这道题与昨天的不同子序列…...

Android studio中如何生成jar包?

文章目录 需求背景目录结构gradle结构makeJar的语法解析 执行makeJar 任务拿到jar包 需求背景 别部门做C语言开发的同学开发了一个库&#xff0c;需要给我们Android端去调用。 我们拿到源码&#xff0c;首先需要做的是通过CMake去把C源码编译链接成动态库。 当然静态库也行&am…...

【2】基于多设计模式下的同步异步日志系统-设计模式

6. 相关技术知识补充 6.1 不定参函数 在初学C语⾔的时候&#xff0c;我们都⽤过printf函数进⾏打印。其中printf函数就是⼀个不定参函数&#xff0c;在函数内部可以根据格式化字符串中格式化字符分别获取不同的参数进⾏数据的格式化。 ⽽这种不定参函数在实际的使⽤中也⾮常…...

第十五届蓝桥杯模拟赛B组(第二期)C++

前言&#xff1a; 第一次做蓝桥模拟赛的博客记录&#xff0c;可能有很多不足的地方&#xff0c;现在将第十五届蓝桥杯模拟赛B组&#xff08;第二期&#xff09;的题目与代码与大家进行分享&#xff0c;我是用C做的&#xff0c;有好几道算法题当时自己做的也是一脸懵&#xff0c…...

企业ERP软件定制开发要注意|app小程序搭建

企业ERP软件定制开发要注意|app小程序搭建 企业ERP软件定制开发是一项复杂而且关键的任务&#xff0c;它需要深入理解企业的需求和流程&#xff0c;并且以此为基础进行设计和开发。以下是一些关于企业ERP软件定制开发的注意事项。 首先&#xff0c;我们必须确保在进行定制开发之…...

系统架构设计-权限模块的设计

系统架构-权限模块的设计 如何评估一个研发人员技术水平&#xff0c;在大部分的情况下不是看其完成业务代码的好坏&#xff0c;更多的时候还是需要看这个研发人员从零构建一个完整项目的能力&#xff0c;在大公司中这样的机会可能相对较少&#xff0c;大部分的时间里都是对现有…...

IDEA切换Python虚拟环境

前言 因为之前一直使用的IDEA开发&#xff0c;换到VSCODE之后各种不习惯&#xff0c;特别是DEBUG的操作&#xff0c;特别难受&#xff0c;因此决心换回IDEA 环境配置 已有项目调整 进入Project 选择SDKs&#xff0c;新建Python 配置Conda以及虚拟环境 有就选择一个虚拟环境…...

《opencv实用探索·十一》opencv之Prewitt算子边缘检测,Roberts算子边缘检测和Sobel算子边缘检测

1、前言 边缘检测&#xff1a; 图像边缘检测是指在图像中寻找灰度、颜色、纹理等变化比较剧烈的区域&#xff0c;它们可能代表着物体之间的边界或物体内部的特征。边缘检测是图像处理中的一项基本操作&#xff0c;可以用于人脸识别、物体识别、图像分割等多个领域。 边缘检测…...

prime靶机打靶记录

靶机下载地址 https://download.vulnhub.com/prime/Prime_Series_Level-1.rar nmap搜索目标 使用nmap -sn 192.168.41.0/24找到目标靶机192.168.41.136 扫描端口&#xff0c;因为是靶机&#xff0c;所以速率直接调了10000 扫出来两个端口22和80&#xff0c;进行详细的扫描 没…...

树莓派,linux换清华源

清华源网址 https://mirrors.tuna.tsinghua.edu.cn/help/raspbian/ 更换软件源 鉴于国内网络环境下载各大镜像&#xff0c;软件包速度慢的问题&#xff0c;需要更换软件源&#xff0c;以防下载慢&#xff0c;且在本教程中&#xff0c;统一更换为清华源。 2.3.1 更换树莓派软…...

公有云迁移研究——AWS DMS

大纲 1 什么是DMS2 DMS的作用3 DMS在迁移的时候都做些什么4 在使用DMS的时候我们需要做些什么5 操作5.1 创建两个数据库终端节点5.2 创建迁移任务 6 可能遇到的问题7 总结 在本地机房或其他云往AWS上做迁移时&#xff0c;往往会遇到数据库迁移的任务。如果数据量不是特别大&…...

一起学docker系列之十七Docker Compose 与手动操作的比较与优势分析

目录 1 前言2 不使用 Docker Compose2.1 启动 MySQL 容器2.2 启动 Redis 容器2.3 启动微服务容器 3 使用 Docker Compose4 使用 Docker Compose 的优势5 结语参考地址 1 前言 在当今容器化应用的开发与部署中&#xff0c;容器编排工具的选择对于简化流程、提高效率至关重要。本…...

IP地址定位不准确的情况研究

在互联网的浩瀚海洋中&#xff0c;每一台连接到网络的设备都被赋予了一个独特的标识符&#xff0c;这就是IP地址。它就像是我们在线身份的一部分&#xff0c;帮助我们与他人进行通信&#xff0c;获取信息&#xff0c;以及享受各种网络服务。然而&#xff0c;由于各种原因&#…...

武汉凯迪正大KDZD5289硫化曲线测试仪(电脑无转子硫化仪)

电脑无转子硫化仪 硫化时间测试仪 硫化曲线仪 硫化曲线测试仪 武汉凯迪正大KDZD5289产品概述 KDZD5289硫化曲线测试仪&#xff08;电脑无转子硫化仪&#xff09;采用电脑控制进口温控仪进行准确控温&#xff0c;计算机适时进行数据处理并可进行统计、分析、存储对比等&#xff…...

Topic和Partition

作用 主题作为消息的一级分类, 分区是对二级分类。分区是Kafka可伸缩性和水平扩展的关键, 也是多副本机制保证可用性的基础。分区可以有一到多个副本, 每个副本对应1个日志文件, 每个日志文件对应1到多个日志分段。每个日志分段又可以细分为日志文件, 索引文件和快照文件。 创…...

算法通关村第十四关|黄金挑战|数据流的中位数

数据流的中位数 原题&#xff1a;力扣295. 设计一种数据结构可以支持添加整数和返回中位数的操作。 之前写过找中间用两个堆&#xff0c;这道题就可以使用一个大顶堆和一个小顶堆。 大顶堆存储比较小的元素&#xff0c;小顶堆存储比较大的元素。 class MedianFinder {Prio…...

挑选数据可视化工具:图表类型、交互功能与数据安全

作为一名数据分析师&#xff0c;我经常需要使用各种数据可视化工具来将数据以直观、清晰的方式呈现出来&#xff0c;以便更好地理解和分析。在市面上的众多可视化工具中&#xff0c;我根据实际需求和项目特点进行选择。本文将从以下几个角度对市面上的数据可视化工具进行对比&a…...

华纳云:有效解决服务器宕机的办法

服务器宕机可能是由多种原因引起的&#xff0c;包括硬件故障、软件问题、网络问题等。以下是一些简单的解决服务器宕机问题的办法&#xff1a; 检查硬件连接&#xff1a; 确保服务器的所有硬件连接正常。检查电源线、网络连接、存储设备连接等&#xff0c;确保没有松动或断开的…...

坦克大战-部分

通过键盘操控坦克移动&#xff0c;转弯&#xff0c;射击 消灭所有敌人可以过关 23个类&#xff0c;3个gif图片 wsad控制移动 j射击 砖墙限制移动&#xff0c;可以打穿&#xff1b;铁墙&#xff0c;限制移动&#xff0c;不能打穿&#xff1b;水&#x…...

OracleRac跨网段修改Public IP/VIP/Private IP/Scan IP

本验证于测试环境&#xff0c;生产操作需谨慎 现为测试环境&#xff0c;机器有且仅有两个网卡存在&#xff0c;需求修改Public IP/VIP/Private IP/Scan IP&#xff0c;把Public IP/VIP/Scan IP的网段改为Private IP的网段&#xff0c;Private IP于Public IP网段互换。 先停掉两…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...