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

news2024/11/16 21:31:39

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

动态规划五部曲:

1,确定dp数组(dp table)以及下标的含义:dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。

2,确定递推公式

  • 当word1[i - 1] 与 word2[j - 1]相同的时候
  • 当word1[i - 1] 与 word2[j - 1]不相同的时候

当word1[i - 1] 与 word2[j - 1]相同的时候,dp[i][j] = dp[i - 1][j - 1];

当word1[i - 1] 与 word2[j - 1]不相同的时候,有三种情况:

情况一:删word1[i - 1],最少操作次数为dp[i - 1][j] + 1

情况二:删word2[j - 1],最少操作次数为dp[i][j - 1] + 1

情况三:同时删word1[i - 1]和word2[j - 1],操作的最少次数为dp[i - 1][j - 1] + 2

那最后当然是取最小值,所以当word1[i - 1] 与 word2[j - 1]不相同的时候,递推公式:dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1});因为 dp[i][j - 1] + 1 = dp[i - 1][j - 1] + 2,所以递推公式可简化为:dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);

3,dp数组如何初始化:从递推公式中,可以看出来,dp[i][0] 和 dp[0][j]是一定要初始化的。dp[i][0]:word2为空字符串,以i-1为结尾的字符串word1要删除多少个元素,才能和word2相同呢,很明显dp[i][0] = i。

4,确定遍历顺序:从递推公式 dp[i][j] = min(dp[i - 1][j - 1] + 2, min(dp[i - 1][j], dp[i][j - 1]) + 1); 和dp[i][j] = dp[i - 1][j - 1]可以看出dp[i][j]都是根据左上方、正上方、正左方推出来的。所以遍历的时候一定是从上到下,从左到右,这样保证dp[i][j]可以根据之前计算出来的数值进行计算。

5,举例推导dp数组:以word1:"sea",word2:"eat"为例,推导dp数组状态图如下:

Java代码如下:

    public int minDistance(String word1, String word2) {
        int len1 = word1.length();
        int len2 = word2.length();
        int[][] dp = new int[len1 + 1][len2 + 1];
        for (int i = 1; i <= len1; i++) {
            for (int j = 1; j <= len2; j++) {
                if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        return len1 + len2 - dp[len1][len2] * 2;
    }

 

LeetCode72. 编辑距离

动态规划五部曲:

1,确定dp数组(dp table)以及下标的含义:dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]

2,确定递推公式:在确定递推公式的时候,首先要考虑清楚编辑的几种操作,整理如下:

if (word1[i - 1] == word2[j - 1])
    不操作
if (word1[i - 1] != word2[j - 1])
    增
    删
    换

也就是如上4种情况。

if (word1[i - 1] == word2[j - 1]) 那么说明不用任何编辑,dp[i][j] 就应该是 dp[i - 1][j - 1],即dp[i][j] = dp[i - 1][j - 1];

为啥要即dp[i][j] = dp[i - 1][j - 1]呢?

那么就在回顾上面讲过的dp[i][j]的定义,word1[i - 1] 与 word2[j - 1]相等了,那么就不用编辑了,以下标i-2为结尾的字符串word1和以下标j-2为结尾的字符串word2的最近编辑距离dp[i - 1][j - 1]就是 dp[i][j]了。

在整个动规的过程中,最为关键就是正确理解dp[i][j]的定义!

if (word1[i - 1] != word2[j - 1]),此时就需要编辑了,如何编辑呢?

  • 操作一:word1删除一个元素,那么就是以下标i - 2为结尾的word1 与 j-1为结尾的word2的最近编辑距离 再加上一个操作。

即 dp[i][j] = dp[i - 1][j] + 1;

  • 操作二:word2删除一个元素,那么就是以下标i - 1为结尾的word1 与 j-2为结尾的word2的最近编辑距离 再加上一个操作。

即 dp[i][j] = dp[i][j - 1] + 1;

怎么都是删除元素,添加元素去哪了。

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

            a                         a     d
   +-----+-----+             +-----+-----+-----+
   |  0  |  1  |             |  0  |  1  |  2  |
   +-----+-----+   ===>      +-----+-----+-----+
 a |  1  |  0  |           a |  1  |  0  |  1  |
   +-----+-----+             +-----+-----+-----+
 d |  2  |  1  |
   +-----+-----+

 操作三:替换元素,word1替换word1[i - 1],使其与word2[j - 1]相同,此时不用增删加元素。

可以回顾一下,if (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 - 1] + 1;

综上,当 if (word1[i - 1] != word2[j - 1]) 时取最小的,即:dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1;

3,dp数组如何初始化:再回顾一下dp[i][j]的定义:dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。那么dp[i][0] 和 dp[0][j] 表示什么呢?dp[i][0] :以下标i-1为结尾的字符串word1,和空字符串word2,最近编辑距离为dp[i][0]。那么dp[i][0]就应该是i,对word1里的元素全部做删除操作,即:dp[i][0] = i;同理dp[0][j] = j;

4,确定遍历顺序:

从如下四个递推公式:

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

可以看出dp[i][j]是依赖左方,上方和左上方元素的,如图:

所以在dp矩阵中一定是从左到右从上到下去遍历。 

5,举例推导dp数组:以示例1为例,输入:word1 = "horse", word2 = "ros"为例,dp矩阵状态图如下:

Java代码如下:

    public int minDistance(String word1, String word2) {
        int m = word1.length();
        int n = word2.length();
        int[][] dp = new int[m + 1][n + 1];
        for (int i = 1; i <= m; i++) {
            dp[i][0] =  i;
        }
        for (int j = 1; j <= n; j++) {
            dp[0][j] = j;
        }
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    dp[i][j] = Math.min(Math.min(dp[i - 1][j - 1], dp[i][j - 1]), dp[i - 1][j]) + 1;
                }
            }
        }
        return dp[m][n];
    }

 

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

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

相关文章

自己尝试在springboot2.0微服务中内嵌一个FTP Server

1.pom.xml添加依赖 <dependency><groupId>org.apache.ftpserver</groupId><artifactId>ftpserver-core</artifactId><version>1.2.0</version></dependency> 2.yml文件添加Ftp服务参数 3.增加apache.ftpserver专用配置文件 文…

OWASO 之认证崩溃基础技能

文章目录 一、burp爆破用法1.Attack type爆破方式设置2.payload处理3.请求引擎设置4.攻击结果设置5.grap匹配设置 二、常见端口与利用1、文件共享2、远程连接3、Web应用4、数据库 三、爆破案例经验1、暴力破解攻击产生的5个原因或漏洞2、猜测用户名方法3、猜测密码方法 四、实验…

第七十三天学习记录:计算机硬件技术基础:微型计算机基础

一、微型计算机的组成&#xff1a; 微型计算机由硬件和软件两大部分组成&#xff0c;硬件是指构成微型计算机的物理实体或物理装置&#xff0c;包括微型计算机的微处理器、储存器、总线接口电路和外部设备&#xff0c;以及电源和机械构件等。软件是指微型计算机所使用的各种程…

Python3数据分析与挖掘建模(11)多因子:复合分析-分组分析与实现示例

1. 分组分析 1.1 概述 分组与钻取是数据分析中常用的技术&#xff0c;用于对数据进行聚合和细分分析。它可以帮助我们从整体数据中获取特定维度的汇总信息&#xff0c;并进一步钻取到更详细的子集数据中进行深入分析。 分组&#xff08;Grouping&#xff09;是指根据某个或多…

SciencePub学术 | 国内高口碑重点SCIEI征稿中

SciencePub学术 刊源推荐: 国内高口碑重点SCI&EI征稿中&#xff01;期刊质量高&#xff0c;接收领域广。信息如下&#xff0c;录满为止&#xff1a; 一、期刊概况&#xff1a; 国内高口碑重点SCI&EI &#x1f4cc;【期刊简介】IF&#xff1a;7.5-8.0&#xff0c;JCR…

python高级-socket和web相关

目录 一、socket 1.客户端开发 2.tcp客户端 3.tcp服务端 4.连接的注意事项 5.多任务服务端 二、静态web 1.请求报文 2.响应头 3.静态web服务器 4.socket静态页面 5.多进程模拟404和200状态码 6.面向对象多任务 结语 一、socket 1.客户端开发 创建客户端套接字对…

anaconda ubuntu安装

1、下载anaconda 地址&#xff1a;https://www.anaconda.com/download#downloads 我是x86 64位系统&#xff0c;所以选择第一个 2、安装 执行命令&#xff1a; sh Anaconda3-2023.03-1-Linux-x86_64.sh中间会有几个过程 enter 确定 yes 确定 最后默认安装位置为&#xff1…

const、let、var区别

const、let、var区别 0、前言1、区别2、示例2.1 提前调用报错2.2 const与 let 定义的变量不能重复2.3 const与 let定义的变量如果在{}中只能在{}中调用2.4 const定义的变量不能重复赋值。 0、前言 let和const是ES6新增的声明变量的关键词&#xff0c;之前声明变量的关键词是var…

SpringBoot+mybatis教务管理系统

项目介绍 主要功能&#xff1a; 这个项目是一个教务管理系统&#xff0c;其中有三种角色&#xff1a;管理员&#xff0c;教师&#xff0c;学生 管理员权限&#xff1a; 管理员&#xff1a;对课程、学生信息、教师信息等进行增删改查&#xff0c;修改个人密码&#xff0c;修改学…

服务日志性能调优,由log引出的巨坑

只有被线上服务问题毒打过的人才明白日志有多重要&#xff01; 谁赞成&#xff0c;谁反对&#xff1f;如果你深有同感&#xff0c;那恭喜你是个社会人了&#xff1a;&#xff09; 日志对程序的重要性不言而喻&#xff0c;轻巧、简单、无需费脑&#xff0c;程序代码中随处可见…

新项目之初性能测试工作如何前移?

最近刚接手一个新项目&#xff0c;在最开始的时候要求对这个项目做性能测试&#xff0c;产品经理也给不出性能需求&#xff0c;只因为这个项目是电商项目&#xff0c;可能会有高并发&#xff0c;秒杀的场景&#xff0c;所以产品经理要求我们对这个项目必须做性能测试&#xff0…

Linux内核中内存管理相关配置项的详细解析16

接前一篇文章&#xff1a;Linux内核中内存管理相关配置项的详细解析15 三十五、Data Access Monitoring 此项展开后如下图所示&#xff1a; “DAMON: Data Access Monitoring Framework”项默认不选中。如果将其选中&#xff0c;则页面变为&#xff1a; 1. DAMON: Data Access…

关于 vue2 后台管理系统构建 vue2+mock.js 的经典案例

一&#xff0c;初识 Mock.js 1.什么是 mock.js: 主要是模拟数据生成器&#xff0c;可以生成随机数据&#xff0c;拦截器 Ajax 请求 2.为什么要使用 mock.js 由于很多学生在学习过程中&#xff0c;后端还没有做好接口&#xff0c;写好接口文档&#xff0c;有了mock.js 前端就…

2023VALSE目标跟踪相关的Poster

前沿&#xff1a;本博文分享了2023 中国无锡举办的VALSE 中与目标跟踪相关的Poster。 1. Weakly Alignment-Free RGBT Salient Object Detection With Deep Correlation Network IEEE TRANSACTIONS ON IMAGE PROCESSING, VOL. 31, 20 摘要&#xff1a;RGBT显著性目标检测&am…

Linux5.4 Mysql数据库初体验及管理

文章目录 计算机系统5G云计算第四章 LINUX Mysql数据库初体验及管理一、数据库相关概念1. 数据 (Data)的概念2.表的概念3.数据库的概念4.数据库管理系统5.数据库系统 二、数据库的发展1.第一代数据库2.第二代数据库3.第三代数据库 三、主流的数据库介绍四、关系数据库1.概念2.E…

最强Postman替代品,国产软件Apifox到底有对牛?

目录 前言&#xff1a; 接口管理现状 一、常用解决方案 二、存在的问题 Apifox 解决方案 一、如何解决这些问题 二、Apifox 做的不仅仅是数据打通 三、后续功能规划 四、更多 Apifox 功能截图 前言&#xff1a; Apifox是一款国产的API接口管理工具&#xff0c;可以帮…

Linux之用户组管理

目录 Linux之用户组管理 创建用户组 --- groupadd命令 语法格式 参数及作用 案例 添加/删除组成员 --- gpasswd命令 命令格式 参数及作用 案例 修改用户组属性 --- groupmod命令 语法格式 参数及作用 案例 删除组账户 --- groupdel命令 语法格式 案例 用户和组…

ASP.NET实验室信息管理系统源码 LIMS系统源码

ASP.NET实验室信息管理系统源码 LIMS系统源码 lims 实验室信息管理系统&#xff08;LIMS&#xff09;。它是由计算机硬件和应用软件组成&#xff0c;能够完成实验室数据和信息的收集、分析、报告和管理。 LIMS实验室信息管理系统专门针对实验室的整体环境而设计&#xff0c;以…

两个链表相加

描述 假设链表中每一个节点的值都在 0 - 9 之间&#xff0c;那么链表整体就可以代表一个整数。 给定两个这种链表&#xff0c;请生成代表两个整数相加值的结果链表。 数据范围&#xff1a;0≤n,m≤1000000&#xff0c;链表任意值 0≤val≤9 要求&#xff1a;空间复杂度 O(n)…

Docker使用记录

文章目录 Docker基本使用Docker配置查看状态卸载安装使用 apt 存储库安装在 Ubuntu 上安装 Docker 桌面(非必要) Docker实例使用现有的镜像查找镜像拖取镜像列出镜像列表更新镜像导出镜像删除镜像导入镜像清理镜像查看容器导出容器导入容器-以镜像的方式创建容器重启容器进入容…