代码随想录算法训练营第四十八天| 115.不同的子序列、583. 两个字符串的删除操作、 72. 编辑距离

115.不同的子序列

在这里插入图片描述

题目链接:115.不同的子序列
文档讲解:代码随想录
状态:不会

思路:
dp[i][j] 表示在 s 的前 j 个字符中,t 的前 i 个字符作为子序列出现的次数。

匹配的情况:
1.当 s[j-1] 与 t[i-1] 匹配时,说明我们可以用 s[j-1] 来匹配 t[i-1],这种情况下,在 s 的前 j-1 个字符中找到的所有 t 的前 i-1 个字符作为子序列的组合数(dp[i-1][j-1])都可以作为当前组合的一部分。例如: t:ba(g) s:bag(g) ,当t[2]=s[3]时,如果使用s[3]的话,dp[2][3]可以由dp[1][2]得到,也就是t:ba(g)在s:bag(g)中的出现次数可以由ba在bag出现的次数推导过来,因为t和s都加上一个相同的g。这是推导dp[i][j]的可能情况之一。
2.此外,即使不使用 s[j-1] 也可以完成匹配,这种情况下,只需要在 s 的前 j-1 个字符中找到 t 的前 i 个字符作为子序列的组合数(dp[i][j-1])。例如:t:ba(g) s:bag(g) ,如果不使用s[3],就是看 t:ba(g) 和 s:ba(g) ,这种情况 dp[2][3] 可以由dp[2][2]得到,也就是t:ba(g)在s:bag(g)中的出现次数可以由t:bag在s:bag出现的次数推导过来。这也是推导dp[i][j]的一种情况。
所以: s[j-1] 与 t[i-1] 匹配时,dp[i][j] = dp[i - 1][j - 1] + dp[i][j - 1];

不匹配的情况:
当 s[j-1] 与 t[i-1] 不匹配时,说明我们不能用 s[j-1] 来匹配 t[i-1]。这种情况下,我们只能在 s 的前 j-1 个字符中找到 t 的前 i 个字符作为子序列的组合数(dp[i][j-1])。

初始状态
空字符串 t 是任何字符串 s 的子序列:因此,对于任何 j,dp[0][j] = 1。
空字符串 s 不能包含非空字符串 t:因此,对于任何 i > 0,dp[i][0] = 0。

题解:

    public int numDistinct(String s, String t) {// 将字符串转换为字符数组char[] sChars = s.toCharArray();char[] tChars = t.toCharArray();// 创建DP数组,dp[i][j]表示t的前i个字符在s的前j个字符中出现的次数int[][] dp = new int[t.length() + 1][s.length() + 1];// 初始化 dp[0][j] 为 1,因为空字符串t是任何字符串s的子序列for (int j = 0; j <= s.length(); j++) {dp[0][j] = 1;}// 填充DP数组for (int i = 1; i <= t.length(); i++) {for (int j = 1; j <= s.length(); j++) {if (tChars[i - 1] == sChars[j - 1]) {// 如果当前字符匹配,可以选择匹配和不匹配两种情况dp[i][j] = dp[i - 1][j - 1] + dp[i][j - 1];} else {// 如果当前字符不匹配,只能不匹配dp[i][j] = dp[i][j - 1];}}}// 返回t的前t.length()个字符在s的前s.length()个字符中出现的次数return dp[t.length()][s.length()];}

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

在这里插入图片描述

题目链接:583. 两个字符串的删除操作
文档讲解:代码随想录
状态:做出来了有点磕绊

思路1:找到最大公共子序列数量,然后两个字符串分别减去它求和。

思路2:
dp[i][j]表示word1[0,i],word2[0,j],要使它们相同一共需要删去多少个字符。

当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
其中情况三隐含在情况一和二中,所以应该是情况1和2中应该取最小操作数,所以dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);

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

题解:

    public int minDistance(String word1, String word2) {// 将字符串转换为字符数组char[] w1 = word1.toCharArray();char[] w2 = word2.toCharArray();// 创建DP数组,dp[i][j]表示word1的前i个字符和word2的前j个字符的最长公共子序列长度int[][] dp = new int[word1.length() + 1][word2.length() + 1];// 填充DP数组for (int i = 1; i <= w1.length; i++) {for (int j = 1; j <= w2.length; j++) {if (w1[i - 1] == w2[j - 1]) {// 如果当前字符匹配,LCS长度加1dp[i][j] = dp[i - 1][j - 1] + 1;} else {// 如果当前字符不匹配,选择两个子问题中LCS最长的一个dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]);}}}// 计算最少步骤:将两个字符串转换成它们的LCS需要的删除和插入操作数return word1.length() + word2.length() - 2 * dp[word1.length()][word2.length()];}public int minDistance2(String word1, String word2) {char[] w1 = word1.toCharArray();char[] w2 = word2.toCharArray();int m = word1.length(), n = word2.length();// 创建DP数组,dp[i][j]表示word1的前i个字符与word2的前j个字符变得相同所需删除的字符数int[][] dp = new int[m + 1][n + 1];// 初始化边界情况:将word1的前i个字符变为空字符串需要i步操作(全删除)for (int i = 1; i <= m; i++) {dp[i][0] = i;}// 初始化边界情况:将空字符串变成word2的前j个字符需要j步操作(全删除)for (int j = 1; j <= n; j++) {dp[0][j] = j;}// 填充DP数组for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {if (w1[i - 1] == w2[j - 1]) {// 当前字符相等,不需要额外删除dp[i][j] = dp[i - 1][j - 1];} else {// 当前字符不相等,选择删除word1[i - 1]或word2[j - 1]中的最小删除次数dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);}}}// 返回最终结果return dp[m][n];}//最少编辑距离思路public int minDistance3(String word1, String word2) {// 将字符串转换为字符数组char[] w1 = word1.toCharArray();char[] w2 = word2.toCharArray();int m = word1.length(), n = word2.length();// 创建DP数组,dp[i][j]表示将word1的前i个字符转换为word2的前j个字符所需的最少操作数int[][] dp = new int[m + 1][n + 1];// 初始化边界情况:word1的前i个字符转换为空字符串需要i步操作(全删除)for (int i = 1; i <= m; i++) {dp[i][0] = i;}// 初始化边界情况:空字符串转换为word2的前j个字符需要j步操作(全插入)for (int i = 1; i <= n; i++) {dp[0][i] = i;}// 填充DP数组for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {if (w1[i - 1] == w2[j - 1]) {// 如果当前字符匹配,不需要额外操作dp[i][j] = dp[i - 1][j - 1];} else {// 如果当前字符不匹配,选择三种操作中的最小值(插入、删除、替换)dp[i][j] = Math.min(dp[i - 1][j] + 1, // 删除操作Math.min(dp[i][j - 1] + 1, // 插入操作dp[i - 1][j - 1] + 1)); // 替换操作}}}// 返回将word1转换为word2所需的最少操作数return dp[m][n];}

72. 编辑距离

在这里插入图片描述

题目链接:72. 编辑距离
文档讲解:代码随想录
状态:不会

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

显然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删除一个元素,那么就是word1[0,i-1] 与 word2[0,j] 的最近编辑距离 再加上一个操作。
即 dp[i][j] = dp[i - 1][j] + 1;

操作二:word2插入一个元素,那么就是word1[0,i] 与 word2[0,j-1] 的最近编辑距离 再加上一个操作。

操作三:替换元素,word1替换word1[i - 1],使其与word2[j - 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 - 1], dp[i - 1][j], dp[i][j - 1]}) + 1;
}

初始化:
word1的前i个字符转换为空字符串需要i步操作(全删除)
空字符串转换为word2的前j个字符需要j步操作(全插入)

题解:

    public int minDistance(String word1, String word2) {// 将字符串转换为字符数组char[] w1 = word1.toCharArray();char[] w2 = word2.toCharArray();int m = word1.length(), n = word2.length();// 创建DP数组,dp[i][j]表示将word1的前i个字符转换为word2的前j个字符所需的最少操作数int[][] dp = new int[m + 1][n + 1];// 初始化边界情况:word1的前i个字符转换为空字符串需要i步操作(全删除)for (int i = 1; i <= m; i++) {dp[i][0] = i;}// 初始化边界情况:空字符串转换为word2的前j个字符需要j步操作(全插入)for (int i = 1; i <= n; i++) {dp[0][i] = i;}// 填充DP数组for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {if (w1[i - 1] == w2[j - 1]) {// 如果当前字符匹配,不需要额外操作dp[i][j] = dp[i - 1][j - 1];} else {// 如果当前字符不匹配,选择三种操作中的最小值(插入、删除、替换)dp[i][j] = Math.min(dp[i - 1][j] + 1, // 删除操作Math.min(dp[i][j - 1] + 1, // 插入操作dp[i - 1][j - 1] + 1)); // 替换操作}}}// 返回将word1转换为word2所需的最少操作数return dp[m][n];}

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

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

相关文章

接口测试(3)

接口自动化 # 获取图片验证码import requestsresponse requests.get(url"http://kdtx-test.itheima.net/api/captchaImage")print(response.status_code) print(response.text) import requestsurl "http://kdtx-test.itheima.net/api/login" header_da…

计算机网络之WPAN 和 WLAN

上一篇文章内容&#xff1a;无线局域网 1.WPAN&#xff08;无线个人区域网&#xff09; WPAN 是以个人为中心来使用的无线个人区域网&#xff0c;它实际上就是一个低功率、小范围、低速率和低价格的电缆替代技术。 &#xff08;1&#xff09; 蓝牙系统(Bluetooth) &#…

QT文件生成可执行的exe程序

将qt项目生成可执行的exe程序可按照以下步骤进行&#xff1a; 1、在qt中构建运行生成.exe文件&#xff1b; 2、从自定义的路径中取出exe文件放在一个单独的空文件夹中&#xff08;exe文件在该文件夹中的release文件夹中&#xff09;&#xff1b; 3、从开始程序中搜索qt&#xf…

CTF php RCE(二)

0x04 php伪协议 这种我们是先看到了include才会想到&#xff0c;利用伪协议来外带文件内容&#xff0c;但是有些同学会问&#xff0c;我们怎么知道文件名是哪个&#xff0c;哪个文件名才是正确的&#xff0c;那么这里我们就得靠猜了 include函数 因为 include 是一个特殊的语…

产品原型设计:从概念到实现的完整指南

如果你是一位产品经理&#xff0c;那么你一定会和原型图打交道&#xff0c;产品原型是产品设计方案和底层逻辑的可视化表达&#xff0c;需要完整清晰地表达出产品目的及需求&#xff0c;在整个产品创造的过程中发挥着不可或缺的作用。而对于一些刚入行的产品经理来说&#xff0…

Instruct-GS2GS:通过用户指令编辑 GS 三维场景

Paper: Instruct-GS2GS: Editing 3D Gaussian Splats with Instructions Introduction: https://instruct-gs2gs.github.io/ Code: https://github.com/cvachha/instruct-gs2gs Instruct-GS2GS 复用了 Instruct-NeRF2NeRF 1 的架构&#xff0c;将基于 NeRF 的三维场景编辑方法迁…

4:表单和通用视图

表单和通用视图 1、编写一个简单的表单&#xff08;1&#xff09;更新polls/detail.html文件 使其包含一个html < form > 元素&#xff08;2&#xff09;创建一个Django视图来处理提交的数据&#xff08;3&#xff09;当有人对 Question 进行投票后&#xff0c;vote()视图…

Python实现吃豆人游戏详解(内附完整代码)

一、吃豆人游戏背景 吃豆人是一款由Namco公司在1980年推出的经典街机游戏。游戏的主角是一个黄色的小圆点&#xff0c;它必须在迷宫中吃掉所有的点数&#xff0c;同时避免被四处游荡的幽灵捉到。如果玩家能够吃掉所有的点数&#xff0c;并且成功避开幽灵&#xff0c;就可以进入…

力扣第一题

1. 两数之和 提示 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可…

【测试设计】使用jenkins 插件Allure生成自动化测试报告

前言 以前做自动化测试的时候一直用的HTMLTestRunner来生成测试报告&#xff0c;后来也尝试过用Python的PyH模块自己构建测试报告&#xff0c;在后来看到了RobotFramework的测试报告&#xff0c;感觉之前用的测试报告都太简陋&#xff0c;它才是测试报告应该有的样子。也就是在…

射频硅基氮化镓:两个世界的最佳选择

当世界继续努力追求更高速的连接&#xff0c;并要求低延迟和高可靠性时&#xff0c;信息通信技术的能耗继续飙升。这些市场需求不仅将5G带到许多关键应用上&#xff0c;还对能源效率和性能提出了限制。5G网络性能目标对基础半导体器件提出了一系列新的要求&#xff0c;增加了对…

【LeetCode刷题笔记】LeetCode.11.盛最多水的容器

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 更多算法知识专栏&#xff1a;算法分析&#x1f525; 给大家跳段街舞感谢…

CSAPP Lab5- MallocLab

实验目标 本实验需要用c语言实现一个动态的存储分配器&#xff0c;也就是你自己版本的malloc&#xff0c;free&#xff0c;realloc函数。 实验步骤 tar xvf malloclab-handout.tar解压文件 我们需要修改的唯一文件是mm.c&#xff0c;包含如下几个需要实现的函数 int mm_ini…

婴幼儿自闭症的六大警示前兆:家长需警惕的早期信号

婴幼儿自闭症是一种复杂的发育障碍&#xff0c;其早期症状往往较为微妙&#xff0c;但若能及早发现并干预&#xff0c;对孩子的成长至关重要。以下是婴幼儿自闭症的六个主要前兆&#xff1a; 首先&#xff0c;目光呆滞与反应迟钝。婴儿期&#xff0c;孩子应能对外界刺激如声音…

读书笔记-Java并发编程的艺术-第4章(Java并发编程基础)-第3节(线程间通信)

文章目录 4.3 线程间通信4.3.1 volatile和synchronized 关键字4.3.2 等待/通知机制4.3.3 等待/通知的经典范式4.3.4 管道输入 / 输出流4.3.5 Thread.join()的使用4.3.6 ThreadLocal的使用 4.3 线程间通信 线程开始运行&#xff0c;拥有自己的栈空间&#xff0c;就如同一个脚本…

Java字符串(String、字符串拼接、原理)

文章目录 一、String字符串1.1创建方式【直接赋值、new一个对象】1.1.1 使用字符串字面值直接赋值&#xff1a;&#xff08;1&#xff09;字符串字面量创建String对象的转换过程&#xff08;2&#xff09;一些方法&#xff08;3&#xff09;说明 1.1.2 使用new关键字创建字符串…

接口测试(1)

什么是接口测试 路线&#xff1a; 项目介绍 URL&#xff1a;统一资源定位符 HTTP协议 请求URL 请求行 请求方法 post/put 请求行 请求数据类型 content-type json 请求数据 请求体 响应状态码 响应行 响应数据类型 content-type json 响应数据 请响应体 用户名&#xf…

Mybatis Plus 3.X版本的insert填充自增id的IdType.ID_WORKER策略源码分析

总结/朱季谦 某天同事突然问我&#xff0c;你知道Mybatis Plus的insert方法&#xff0c;插入数据后自增id是如何自增的吗&#xff1f; 我愣了一下&#xff0c;脑海里只想到&#xff0c;当在POJO类的id设置一个自增策略后&#xff0c;例如TableId(value "id",type …

Git 命令行快速入门

前言 &#xff08;1&#xff09;新手个人建议使用TortoiseGit这类图形化界面来上手学习。 &#xff08;2&#xff09;如果一定需要用命令行进行操作&#xff0c;可以按照B站&#xff1a;程式与网页开发者必备技能&#xff01;Git 和 GitHub 零基础快速上手&#xff0c;轻松掌握…

干货:高水平论文写作思路与方法

前言:Hello大家好,我是小哥谈。高水平论文的写作需要扎实的研究基础和严谨的思维方式。同时,良好的写作技巧和时间管理也是成功的关键。本篇文章转载自行业领域专家所写的一篇文章,希望大家阅读后可以能够有所收获。🌈 目录 🚀1.依托事实/证据,通过合理的逻辑,…