代码随想录day56 | 动态规划P16 | ● 583. ● 72. ● 编辑距离总结篇

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

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

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

示例 1:

输入: word1 = "sea", word2 = "eat"
输出: 2
解释: 第一步将 "sea" 变为 "ea" ,第二步将 "eat "变为 "ea"

示例 2:

输入:word1 = "leetcode", word2 = "etco"
输出:4

思路

动态规划1

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

递推:

还是分为当前相等/不相等

        相等则dp[i][j] = dp[i - 1][j - 1];(不需要删除,次数不涨)

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

情况一:删word1[i - 1],最少操作次数为dp[i - 1][j] + 1(这里的+1是删除i-1)

情况二:删word2[j - 1],最少操作次数为dp[i][j - 1] + 1(这里的+1是删除j-1)

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

初始化: 按照dp定义 首列初始化为列下标 首行初始化为行下标

动态规划2

求两字符串的最大公共子序列的长度, 然后用字符串长度去减

那么求最大公共子序列:

定义:dp[i][j] 表示以0 到 i-1为的字符串word1,和以 0 到 j-1位的字符串word2两字符串的最长公共子序列长度

递推:

如果text1[i - 1] 与 text2[j - 1]相同,那么找到了一个公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1;

如果text1[i - 1] 与 text2[j - 1]不相同,那就看看text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大的。

初始化:按照dp定义 全0即可

代码

动态规划1

class Solution {
    public int minDistance(String word1, String word2) {
        //dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。
        int [][] dp = new int [word1.length()+1][word2.length()+1];
        for(int i = 0; i <= word1.length(); i++){
            dp[i][0] = i;
        }
        for(int j = 0; j<= word2.length(); j++){
            dp[0][j] = j;
        }

        for(int i = 1; i <= word1.length();i++){
            for(int j = 1; j<=word2.length(); j++){
                if(word1.charAt(i-1) == word2.charAt(j-1)){
                    dp[i][j] = dp[i-1][j-1];
                }else{
                    //dp[i][j - 1] + 1 = dp[i - 1][j - 1] + 2
                    dp[i][j] = Math.min(dp[i][j-1] + 1, dp[i-1][j] + 1);
                }
            }
        }
        return dp[word1.length()][word2.length()];
    }
}

动态规划2

class Solution {
    public int minDistance(String word1, String word2) {
        //dp[i][j] 表示以0 到 i-1为的字符串word1,和以 0 到 j-1位的字符串word2两字符串的最长公共子序列长度
        int [][] dp = new int [word1.length()+1][word2.length()+1];

        for(int i = 1; i <= word1.length();i++){
            for(int j = 1; j<=word2.length(); 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 word1.length() + word2.length() - 2 * dp[word1.length()][word2.length()] ;
    }
}

72. 编辑距离 

给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

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

示例 1:

输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')

示例 2:

输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')

思路

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

递推:

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

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

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

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;

初始化:按照dp定义 首列初始化为列下标 首行初始化为行下标

代码

class Solution {
    public int minDistance(String word1, String word2) {
        int len1 = word1.length(), len2 = word2.length();
        //word1 0到i-1转为 word2 0到j-1的最少操作数
        int [][] dp = new int [len1 + 1][len2 + 1];
        for(int i = 0; i <= len1 ; i++){
            dp[i][0] = i;
        }
        for(int j = 0; j <= len2; j++){
            dp[0][j] = j;
        }
        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];
                }else{
                    int del1 = dp[i-1][j] + 1; // 删除word1中字符i-1
                    int del2 = dp[i][j-1] + 1; // 删除word2中字符j-1
                    //删除某个word中的字符 与 在另一个word中添加 是等价的 故只需要计算删除即可
                    int rep = dp[i-1][j-1] + 1; //替换字符
                    int min = Math.min(del1, del2);
                    min = Math.min(min, rep);
                    dp[i][j] = min;
                }
            }
        }
        return dp[len1][len2];
    }
}

编辑距离总结篇   

代码随想录 (programmercarl.com)

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

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

相关文章

MahApps.Metro的MVVM模式介绍(一)

MahApps.Metro是一个开源的WPF (Windows Presentation Foundation) UI 控件库。它的特点有现代化设计、主题定制、响应式布局、内置控件。 而Mvvm模式的核心思想是将用户界面&#xff08;View&#xff09;与应用程序逻辑&#xff08;ViewModel&#xff09;分离&#xff0c;以实…

55. 【Android教程】位图:Bitmap

在上一节学习 Drawable 图像资源的时候我们在很多地方用到了 bitmap&#xff0c;bitmap 其实就是真实图片在 Android 中最直接的表现形式&#xff0c;这一节我们来仔细学习一下 Bitmap 的使用。 1. 什么是 Bitmap Bitmap 在 Android 中对应一张图片文件&#xff0c;它是一个二…

使用IIS部署Vue项目

前提 使用IIS部署Vue项目&#xff0c;后端必须跨域&#xff0c;不要在Vue中用proxy跨域&#xff0c;那个只在dev环境中有用&#xff01; IIS安装&#xff0c;不用全部打勾&#xff0c;有些他默认就是方块 ■ 选择性安装的&#xff0c;就维持原样就可以。 添加网站配置 右键…

nginx模型设计和进程讲解

一. Nginx进程模型解析 1. master主进程 和 worker工作进程 [rootlocalhost sbin]# ps -ef|grep nginx root 15411 1 0 21:08 ? 00:00:00 nginx: master process ./nginx nobody 15412 15411 0 21:08 ? 00:00:00 nginx: worker process root…

通过颜色学习css

文章目录 1.生成html2.添加css链接3.将h1标签text-align元素4.添加div标签4.1、为类marker添加元素4.2、添加两个新的div标签4.3、修改div标签的类型并修改css元素4.4、为类container添加元素4.5、以数字形式添加颜色4.5、container添加padding属性4.6、组合css中的颜色属性4.7…

python abs函数怎么用

abs()函数是Python的数字函数&#xff0c;用以返回数字的绝对值。 语法 以下是 abs() 方法的语法&#xff1a; abs( x ) 参数 x -- 数值表达式&#xff0c;可以是整数&#xff0c;浮点数&#xff0c;复数。 返回值 函数返回 x&#xff08;数字&#xff09;的绝对值&#x…

【自然语言处理】seq2seq模型——机器翻译

seq2seq模型——机器翻译 1 任务目标 1.1 案例简介 seq2seq是神经机器翻译的主流框架&#xff0c;如今的商用机器翻译系统大多都基于其构建&#xff0c;在本案例中&#xff0c;我们将使用由NIST提供的中英文本数据训练一个简单的中英翻译系统&#xff0c;在实践中学习seq2se…

uniapp文本框上下滚动问题

一个基本需求&#xff0c;textarea标签没有办法通过手拖动的方式进行滚动&#xff0c;当文字超出其容量后&#xff0c;想要编辑上面被遮挡部分的文字这边难以点到&#xff0c;电脑可以鼠标滚轮&#xff0c;但手机需要拖动但无效&#xff1a; 下面提供了我的解决思路&#xff1a…

list的模拟实现

目录 1.默认成员函数模拟实现 1.1 构造函数&#xff08;头节点&#xff09; 1.2 析构函数 1.3 拷贝构造函数 1.4 赋值重载函数 2.增删查改模拟实现 2.1 insert 2.2 erase 2.3 push_back、pop 3.前置、--、后置、-- 3.1前置&#xff1a; 3.2后置&#xff1a; 3.3 …

STC89C52驱动XPT2046AD转换

目录 简介封装接线&#xff08;单端&#xff09;时序以及命令字SPI时序命令字 程序XPT2046.CXPT2046.hmain.c测试 简介 XPT2046是一款4线电阻式触摸屏控制器&#xff0c;采用12位125 kHz采样SAR类型A / D转换器。XPT2046工作电压低至2.2V&#xff0c;支持1.5V至VCC的数字I/O接…

休斯《公共管理导论》第5版/考研真题解析/章节题库

第一部分 考研真题精选 一、概念题二、简答题三、论述题四、案例分析题第二部分 章节题库 第1章 一个变革的时代第2章 政府的角色第3章 传统的公共行政模式第4章 公共管理第5章 公共政策第6章 治 理第7章 问 责第8章 利害关系人和外部环境第9章 管制、外包和公共企…

jenkins目录下的vue3项目——pnpm install后运行报错——奇葩问题解决

昨天到今天&#xff0c;同事那边遇到一个问题&#xff0c;就是关于vue3vite的项目&#xff0c;在执行了自动打包后&#xff0c;运行代码会提示报错的问题。 报错信息如下&#xff1a; 具体错误信息如下&#xff1a; ERROR 11:28:14 [vite] Pre-transform error: Cannot find …

Xshell连接提示“SSH服务器拒绝了密码”

原因1&#xff1a;数字锁没有打开 没有打开NumLock&#xff08;数字小键盘上面有一个【Num】按键&#xff09;&#xff0c;需要按键开启。 注意要检查NumLock灯是否亮起。 或者改成用字母键上面的数字键输入就好了。 原因2&#xff1a;root密码设置错误&#xff08;这个是比较常…

frp内网穿透服务搭建与使用

frp内网穿透服务搭建与使用 1、frp简介 frp 是一个专注于内网穿透的高性能的反向代理应用&#xff0c;支持 TCP、UDP、HTTP、HTTPS 等多种协议。 可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。frp工作原理 服务端运行&#xff0c;监听一个主端口…

深入Django:用户认证与权限控制实战指南

title: 深入Django&#xff1a;用户认证与权限控制实战指南 date: 2024/5/7 18:50:33 updated: 2024/5/7 18:50:33 categories: 后端开发 tags: AuthDecoratorsPermissionsGuardianRESTAuthSessionMgmtMFA 第1章&#xff1a;入门Django与设置 1.1 Django安装与环境配置 在…

netty 高性能架构设计--零拷贝

文章目录 前言一、直接内存1.1 什么是直接内存1.2 代码实现1.3 使用直接内存的优缺点 二、netty 零拷贝设计2.1 netty 直接内存2.2 netty 内存池 三、零拷贝的两种方式 前言 本篇从源码层面剖析 netty 高性能架构设计之零拷贝&#xff0c;并且扩展讲述零拷贝的两种实现方式。 …

并发编程之阻塞队列BlockingQueue实战及其原理分析

1. 阻塞队列介绍 1.1 队列 是限定在一端进行插入&#xff0c;另一端进行删除的特殊线性表。 先进先出(FIFO)线性表。 允许出队的一端称为队头&#xff0c;允许入队的一端称为队尾。

机器学习第二天(监督学习,无监督学习,强化学习,混合学习)

1.是什么 基于数据寻找规律从而建立关系&#xff0c;进行升级&#xff0c;如果是以前的固定算式那就是符号学习了 2.基本框架 3.监督学习和无监督式学习&#xff1a; 监督学习&#xff1a;根据正确结果进行数据的训练&#xff1b; 在监督式学习中&#xff0c;训练数据包括输…

简易录制视频做3D高斯

系统环境 ubuntu20 &#xff0c;cuda11.8&#xff0c;anaconda配置好了3D高斯的环境。 具体参考3D高斯环境配置&#xff1a;https://blog.csdn.net/Son_of_the_Bronx/article/details/138527329?spm1001.2014.3001.5501 colmap安装&#xff1a;https://blog.csdn.net/Son_of…

W801学习笔记二十一:英语背单词学习应用——上

英语背单词是比较常见的学习APP&#xff0c;参考唐诗宋词应用&#xff0c;本章做一个类似的应用。 一、单词数据清洗及格式转换 诗词数据的获取渠道很多&#xff0c;一般可以按照年级来分文件。如一到九年级&#xff0c;四六级&#xff0c;雅思等等。 1、先从网上某某地方下载…