第五十五天| 583. 两个字符串的删除操作、72. 编辑距离

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

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

题干:给定两个单词 word1 和 word2 ,返回使得 word1 和  word2 相同所需的最小步数

每步 可以删除任意一个字符串中的一个字符。

思考:动态规划。本题中的步数可以看作删除字母,使得两单词最终处理为相同字母组。

  • 确定dp数组(dp table)以及下标的含义

dp[i][j]:使得 以i - 1结尾的单词word1和以j - 1结尾的单词word2 相同所需的最小步数。

  • 确定递推公式

从dp[i][j]的定义可以看出,字母比较就两种情况

  • 当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);

  • dp数组如何初始化

从递推公式中,可以看出来,dp[i][0] 和 dp[0][j]是一定要初始化的。

dp[i][0]:word2为空字符串,以i-1为结尾的字符串word1要删除多少个元素,才能和word2相同呢,很明显dp[i][0] = i。同理 dp[0][j] = j。

  • 确定遍历顺序

从递推公式 dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + 1; 和dp[i][j] = dp[i - 1][j - 1]可以看出dp[i][j]都是根据左上方、正上方、正左方推出来的。

所以遍历的时候一定是从上到下,从左到右,这样保证dp[i][j]可以根据之前计算出来的数值进行计算。

  • 举例推导dp数组

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

代码:

class Solution {
public:
    int minDistance(string word1, string word2) {
        //dp[i][j]:使得 以i - 1结尾的单词word1和以j - 1结尾的单词word2 相同所需的最小步数 
        vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1));
        for (int i = 1; i <= word1.size(); i++)     //单词word2为空的情况
            dp[i][0] = i;
        for (int j = 1; j <= word2.size(); j++)     //单词word1为空的情况
            dp[0][j] = j;

        for (int i = 1; i <= word1.size(); i++) {           //遍历单词word1
            for(int j = 1; j <= word2.size(); j++) {        //遍历单词word2
                if (word1[i - 1] == word2[j - 1])
                    dp[i][j] = dp[i - 1][j - 1];        //字母相同则无需无需删除字母
                else
                    dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + 1;     //字母不相同则选一单词删除字母,取最小值
            }
        }
        return dp[word1.size()][word2.size()];
    }
};

思考:动态规划。本题也可以从求公共子序列入手,要删除的元素个数(即步数)为两单词长度减去两倍公共子序列长度。具体如何求公共子序列:1143 最长公共子序列

代码: 

class Solution {
public:
    int minDistance(string word1, string word2) {
        //dp[i][j]:单词word1的处理区间[0, i - 1]与单词word2的处理区间[0, j - 1]中,存在的最长公共子序列的长度
        vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1, 0));     

        for (int i = 1; i <= word1.size(); i++) {           //遍历单词word1
            for (int j = 1; j <= word2.size(); j++) {       //遍历单词word2
                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 word1.size() + word2.size() - 2 * dp[word1.size()][word2.size()];        //两单词去除最长公共子序列
    }
};

Leetcode 72. 编辑距离

题目链接:72 编辑距离

题干:给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数  。你可以对一个单词进行如下三种操作:

  • 插入一个字符
  • 删除一个字符
  • 替换一个字符

思考:动态规划。本题要先想清楚:真正要求的是将word1和word2变成相同单词的操作次数。

题干中删除word1字母的操作 可以等价为 插入word2字母的操作;插入word1字母的操作 可以等价为 删除word2字母的操作。下面就直接考虑删除操作不考虑插入操作。

因此本题与上题的区别在 确定递推公式中:

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

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

情况二:删word2[j - 1](同向word1中插入),最少操作次数为dp[i][j - 1] + 1

情况三:替换word1[i - 1],最少的操作次数为dp[i - 1][j - 1] + 1

当然要取最小值,所以当word1[i - 1] 与 word2[j - 1]不相同的时候,递推公式:dp[i][j] = min({dp[i - 1][j - 1] + 1, dp[i - 1][j] + 1, dp[i][j - 1] + 1});

代码:

class Solution {
public:
    int minDistance(string word1, string word2) {
        //dp[i][j]:对以i- 1结尾的单词word1和以j - 1结尾的单词word2操作,让处理后两单词相同的最少操作次数
        vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1));
        
        for (int i = 0; i <= word1.size(); i++)     //单词word2为空的情况
            dp[i][0] = i;
        for (int j = 1; j <= word2.size(); j++)     //单词word1为空的情况
            dp[0][j] = j;

        for (int i = 1; i <= word1.size(); i++) {           //遍历单词word1
            for (int j = 1; j <= word2.size(); j++) {       //遍历单词word2
                if (word1[i - 1] == word2[j - 1])
                    //当前两字母相同则不用处理
                    dp[i][j] = dp[i - 1][j - 1];    
                else
                    //当前两字母不同则考虑替换word1的字母,删除word1的字母以及删除word2的字母
                    dp[i][j] = min(dp[i - 1][j - 1], min(dp[i - 1][j], dp[i][j -1])) + 1;
            }
        }
        return dp[word1.size()][word2.size()];
    }
};

自我总结:

        理解公共子序列问题的关键在于删除操作,两字符串的操作含义同dp数组的含义变化而变化。动态规划是在每次操作中考虑每种情况,统一处理。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络原理(网络协议初识)

目录 1.网络通信基础 1.1IP地址 1.2端口号 1.3认识协议 1.4五元组 1.5 协议分层 2.TCP/IP五层&#xff08;或四层&#xff09;模型 2.1网络设备所在分层 2.2网络分层对应 3.封装和分用 1.网络通信基础 网络互连的目的是进行网络通信&#xff0c;也即是网络数据传输&#…

Maven简单入门

Maven 一&#xff1a;什么是Maven&#xff1a; Maven是一个项目管理工具&#xff0c;用于构建和管理Java项目。它可以帮助开发人员自动化构建过程&#xff0c;管理项目依赖关系&#xff0c;并协助项目的发布和部署。通过Maven&#xff0c;开发人员可以定义项目的结构、依赖关…

Dubbo:常见的面试题和答案

请关注微信公众号&#xff1a;拾荒的小海螺 1、什么是 Dubbo&#xff1f;它的作用是什么&#xff1f; 答&#xff1a; Dubbo 是一款高性能的 Java RPC 框架&#xff0c;是阿里巴巴公司开源的产品&#xff0c;用于提供高性能的分布式服务框架和面向服务的架构。Dubbo 的主要作…

网络编程套接字(4)——Java套接字(TCP协议)

目录 一、Java流套接字通信模型 二、TCP流套接字编程 1、ServerSocket ServerSocket构造方法&#xff1a; ServerSocket方法: 2、Socket Socket构造方法&#xff1a; Socket方法&#xff1a; 三、代码示例&#xff1a;回显服务器 1、服务器代码 代码解析 2、客户端…

C盘清理_

1.通过注册表来找没有删干净的文件 a.winr b.输入regedit,找到下图相应路径,开始查找,或是选择计算机ctrlf搜索对应的文件夹名

基于springboot+vue实现乌鲁木齐南山冰雪旅游服务网管理系统项目【项目源码+论文说明】

基于springbootvue实现南山冰雪旅游服务网演示 摘要 随着2022年北京冬奥会的成功举办&#xff0c;在冬天进行冰雪运动已经逐渐流行起来&#xff0c;人们慢慢享受到了冰雪活动给大家带来的欢乐&#xff0c;除此之外人们的身体素质也可以得到提升。虽然已经有一部分人可以接受并…

window server2012 卸载iis后,远程连接黑屏

原因分析&#xff1a; 因为自己在卸载IIS的时候&#xff0c;不小心卸载了.net framework&#xff0c;系统没有了图形界面&#xff08;由完整模式Full变为了核心模式core&#xff09;&#xff0c;需要重新恢复.net framework4.5。 解决方法分析&#xff1a; 需要将核心模式co…

WorldGPT、Pix2Pix-OnTheFly、StyleDyRF、ManiGaussian、Face SR

本文首发于公众号&#xff1a;机器感知 WorldGPT、Pix2Pix-OnTheFly、StyleDyRF、ManiGaussian、Face SR HandGCAT: Occlusion-Robust 3D Hand Mesh Reconstruction from Monocular Images We propose a robust and accurate method for reconstructing 3D hand mesh from m…

影城管理系统|基于springboot框架+ Mysql+Java+B/S架构的影城管理系统设计与实现(可运行源码+数据库+设计文档+部署说明)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 前台功能效果图 管理员功能登录前台功能效果图 系统功能设计 数据库E-R图设计 lunwen参考 摘要 研究…

MISC-Catflag

前言 开始拿到这道题&#xff0c;以为是要识别文件类型&#xff0c;后面发现不是&#xff0c;kali识别为ascii文本文件。而用010editor打开&#xff0c;又是一堆看不懂的码 后面发现有很多重复内容1B 5B 43等等&#xff0c;再看题目type flag or cat flag可以联想linux的cat命…

Affinity Designer:超越想象,打造独一无二的设计作品!mac/win版

Affinity Designer是一款功能强大的图形设计软件&#xff0c;它拥有广泛的工具和功能&#xff0c;可以满足各种设计需求。无论是平面设计师、UI/UX设计师、插画师还是摄影师&#xff0c;Affinity Designer都能为他们提供所需的工具和支持。 Affinity Designer 软件获取 Affin…

Oracle 配置多个缓冲池(Keep pool Recycle Pool)

默认情况下&#xff0c;Oracle只有一个缓冲池 - Buffer Cache&#xff0c;其可以满足基本数据缓存需求。但某些数据的访问模式可能与普通数据不同&#xff0c;对于访问非常频繁的数据和很少访问的数据&#xff08;两种极端&#xff09;&#xff0c;Oracle可以支持配置两个独立的…

鸿蒙到底好不好?要不要搞?

相信各位搞安卓的小伙伴多多少少都了解过鸿蒙&#xff0c;有些一知半解而有些已经开始学习起来了。 鸿蒙到底好不好&#xff1f;要不要搞&#xff1f; Android开发反正目前工作感觉也不好找&#xff0c;即便是上海这样的大城市也难搞&#xff0c;人员挺饱和的。而且年前裁员的…

寒假作业Day 12

寒假作业Day 12 一、选择题 队列是先进先出的线性表&#xff0c;既能插入数据&#xff0c;也能删除数据 A&#xff1a;ABCD&#xff0c;一进栈就出栈&#xff1b;B&#xff1a;DCBA&#xff0c;全部进栈之后再出栈 C&#xff1a;ACBD&#xff0c;先进A&#xff0c;然后出&…

“禁止互撕”新规第二天,热搜把#章子怡“怒怼”网友#推上了榜一

3月12日&#xff0c;微博热搜发布公告&#xff0c;对热搜词条处置规则进行了更新。 针对热搜词条长期以来存在的引战互撕、挑唆对立等不良现象&#xff0c;热搜生态秩序亟待改善&#xff0c;微博给出了两大解决方案&#xff1a; 一是更新热搜词条处置规则&#xff0c;当热搜词…

【C++】string的底层剖析以及模拟实现

一、字符串类的认识 C语言中&#xff0c;字符串是以\0结尾的一些字符的集合&#xff0c;为了操作方便&#xff0c;C标准库中提供了一些str系列的库函数&#xff0c; 但是这些库函数与字符串是分离开的&#xff0c;不太符合OOP的思想&#xff0c;而且底层空间需要用户自己管理&a…

[LeetCode][110]平衡二叉树

题目 110.平衡二叉树 给定一个二叉树&#xff0c;判断它是否是平衡二叉树。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;true 示例 2&#xff1a; 输入&#xff1a;root [1,2,2,3,3,null,null,4,4] 输出&#xff1a;false 示例 3&…

ROS 语音交互(三) tts

目录 一、模型选择 二、流程 三、核心代码展示 一、模型选择 科大讯飞超拟人识别 二、流程 超拟⼈合成协议 | 讯飞开放平台文档中心 (xfyun.cn) 三、核心代码展示 # coding: utf-8 import _thread as thread import os import time import base64import base64 import …

一种基于宏和serde_json实现的rust web中统一返回类

本人rust萌新&#xff0c;写web碰到了这个&#xff0c;基于ChatGPT和文心一言学了宏&#xff0c;强行把这玩意实现出来了&#xff0c;做个学习记录&#xff0c;如果有更好的方法&#xff0c;勿喷。 先看效果&#xff0c;注意不支持嵌套&#xff0c;且kv映射要用>(因为它这个…

【LeetCode热题100】142. 环形链表 II(链表)

一.题目要求 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统…