Studying-代码随想录训练营day44| 1143.最长公共子序列、1035.不相交的线、53.最大子序和、392.判断子序列

第44天,动态规划part11,子序列题型part02(ง •_•)ง💪,编程语言:C++

目录

1143.最长公共子序列

1035.不相交的线

53.最大子序和

392.判断子序列

总结


1143.最长公共子序列

文档讲解:代码随想录最长公共子序列

视频讲解:手撕最长公共子序列

题目:1143. 最长公共子序列 - 力扣(LeetCode)

学习:本题与最大重复子数组的不同在于,本题的序列不要求连续。类似于“最长上升子序列”和“最长连续递增序列”的区别。因此本题最大的不同就在于dp数组的设置以及递推公式。

从动归五部曲出发:

1.确定dp数组以及下标的含义:由于本题是子序列,不要求元素之间是连续的。因此本题可设置一个二维dp数组,dp[i][j]表示长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j]。至于为什么是i - 1和 j - 1。其实是和上题一样,简化初始化步骤,否则需要对第一行和第一列单独进行初始化。

2.确定递推公式:主要有两个判断情况:text1[i - 1] 与 text2[j - 1]相同,text1[i - 1] 与 text2[j - 1]不相同。如果text1[i - 1] 与 text2[j - 1]相同,那么找到了一个公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1; 如果text1[i - 1] 与 text2[j - 1]不相同,那就看看dp[i - 1][j] 和 dp[i][j - 1]的情况,取最大值,这个地方其实是包含了两个字符串能否删减的思想,因为一个是比较text1[0, i - 2]与text2[0, j - 1],另一个是比较text1[0, i - 1]与text2[0, j - 2],相当于是每个字符串都考虑少一个元素的情况。这个思想在后面的题目中也有所体现。

3.dp数组初始化:由于我们设置的是i - 1和 j - 1,因此第一行和第二行设置为0即可,其余的情况会自行得到。

4.确定遍历顺序:由递推公式明显可以,有三个方向可以推出dp[i][j]。因此遍历顺序可以为从上到下,从左到右。

5.举例推导dp数组:

代码:

//时间复杂度O(n*m)
//空间复杂度O(n*m)
class Solution {
public:int longestCommonSubsequence(string text1, string text2) {if(text1.size() == 0 || text2.size() == 0) return 0;//动态规划  //1.确定dp数组以及下标的含义://dp[i][j]长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j]vector<vector<int>> dp(text1.size() + 1, vector<int> (text2.size() + 1, 0));//2.确定递推公式//判断text1[i - 1] 和 text2[j - 1]的两种可能//3.初始化dp数组:第一行和第一列为0//4.确定遍历顺序for(int i= 1; i <= text1.size(); i++) {for(int j = 1; j <= text2.size(); j++) {if(text1[i - 1] == text2[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 dp[text1.size()][text2.size()];}
};

1035.不相交的线

文档讲解:代码随想录不相交的线

视频讲解:手撕不相交的线

题目:1035. 不相交的线 - 力扣(LeetCode)

学习:本题实际上是上一题的一个应用,由于只有相等的数能够连线,且不能够出现相交的线。那么就可以认为是找到最长的公共子序列,且子序列之间顺序不能调换。这样和上一题就是一摸一样的了,因此本题的解法也和上一题如出一辙。求解的最大连线数,也就是求解最长的公共子序列和。

因此本题的代码和上一题相同:

代码:

//时间复杂度O(n*m)
//空间复杂度O(n*m)
class Solution {
public:int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {//动态规划:1.确定dp数组以及下标的含义//dp[i][j]:表示nums1数组下标[0-(i - 1)]和nums2数组下标[0-(j-1)]内最大的公共子序列vector<vector<int>> dp(nums1.size() + 1, vector<int>(nums2.size() + 1, 0));//2.确定递推公式:同样试分析nums1[i - 1]和nums2[j - 1]的两种可能//3.初始化dp数组:由于我们使用了i-1和j-1下标,第一行和第一列初始化为0即可//4.确定遍历顺序int result = 0; //记录答案for(int i = 1; i <= nums1.size(); i++) {for(int j = 1; j <= nums2.size(); j++) {if(nums1[i - 1] == nums2[j - 1]) {dp[i][j] = dp[i - 1][j - 1] + 1;}else {dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);}if(result < dp[i][j]) {result = dp[i][j];}}}return result;}
};

53.最大子序和

文档讲解:代码随想录最大子序和

视频讲解:手撕最大子序和

题目:53. 最大子数组和 - 力扣(LeetCode)

学习:本题有两种解题方法。第一种是使用贪心算法,我们只需要保证每次进行加减的是正数即可,因为正数才会对后续的加减产生有利的影响,这在我们贪心算法章节写写过:

代码:贪心算法

//时间复杂度O(n)
//空间复杂度O(1)
class Solution {
public:int maxSubArray(vector<int>& nums) {int count = 0; //记录当前和int maxcount = INT_MIN; //记录最大值for(int i = 0; i < nums.size(); i++) {//如果当前和小于0,抛弃前和,改为当前值if(count < 0) {count = nums[i];}else {count += nums[i];}//如果当前和大于最大值,更新最大值if (count > maxcount) {maxcount = count;}}return maxcount;}
};

第二种方法则是采用动态规划的方式,从动归五部曲出发进行分析。

1.确定dp数组以及下标的含义:首先我们可以设置一个以为dp数组,dp[i]我们肯定是想要让它能够表示[0-i]区间内的最大和,这样dp[nums.size() - 1]就是要我们求解的值。但本题却不可以这么设置,因为本题要求的是子数组,是连续的元素。也就意味着实际上本题和“最大重复子数组”是一样的。我们确定nums[i]的时候,就已经对区间有限制了,必须要包含nums[i]。因此本题dp[i]表示包括下标i(以nums[i]为结尾)的最大连续子序列和为dp[i]

2.确定递推公式:根据设置的含义,可以推出,dp[i]只能从两个方向推出:dp[i - 1] + nums[i],即:nums[i]加入当前连续子序列和;nums[i],即:从头开始计算当前连续子序列和。这两种可能,因为我们是不能够跨元素来取值的,因此只能借前面的值或者就只要当前的值。

3.初始化dp数组:显然dp[0] = nums[0],表示第一个元素的值。

4.确定遍历顺序:递推公式中dp[i]依赖于dp[i - 1]的状态,需要从前向后遍历。

5.举例推导dp数组:

代码:

//时间复杂度O(n)
//空间复杂度O(n)
class Solution {
public:int maxSubArray(vector<int>& nums) {if(nums.size() == 1) return nums[0];//动态规划//1.确定dp数组以及下标的含义vector<int> dp(nums.size(), 0); //dp[i]表示以下标i结尾的连续子数组的最大和//2.确定递推公式//dp[i] = max(nums[i], dp[i - 1] + nums[i]);//3.初始化dp数组dp[0] = nums[0];int result = dp[0]; //保存答案//4.确定遍历顺序for(int i = 1; i < nums.size(); i++) {dp[i] = max(nums[i], dp[i - 1] + nums[i]);if(result < dp[i]) {result = dp[i];}}return result;}

392.判断子序列

文档讲解:代码随想录判断子序列

视频讲解:手撕判断子序列

题目: 392. 判断子序列 - 力扣(LeetCode)

学习:本题又是找子序列,稍微不同的是,本题需要我们判断s是否为t的子序列。其实也可以理解为t和s的最长公共子序列就是s,换句话说,只要t和s的最长公共子序列的长度是s.size(),那么就说明s是t的子序列,因为最长就只能达到s.size()这么长了。

由此本题的解法和最长公共子序列是一样的,只有一处可以进行部分修改,也就是递推公式,由于本题是判断是否是子序列,不需要我们真的找到最长子序列的长度,因此本题可以认为字符串s的各个字符是必须要包含的,因此当s[i - 1] 和 t[i - 1]不等时,可直接dp[i][j] = dp[i][j - 1],不用管s[i-1]的情况,因为字符串s是不能够减少的。(当然不改也不会有错误)

代码:

//时间复杂度O(n*m)
//空间复杂度O(n*m)
class Solution {
public:bool isSubsequence(string s, string t) {//1.确定dp数组以及下标的含义vector<vector<int>> dp(s.size() + 1, vector<int>(t.size() + 1, 0));for(int i = 1; i <= s.size(); i++) {for(int j = 1; j <= t.size(); j++) {if(s[i - 1] == t[j - 1]) {dp[i][j] = dp[i - 1][j - 1] + 1;}else {dp[i][j] = dp[i][j - 1]; //不同点,因为s字符串每个字符都必须考虑}}}return dp[s.size()][t.size()] == s.size();}
};

本题还有时间复杂度更低的解法,直观的一种就是可以采用双指针的解法,因为本题只需要判断一个字符串在另一个字符串中是否出现。

//时间复杂度O(n + m)
//空间复杂度O(1)
class Solution {
public:bool isSubsequence(string s, string t) {int n = s.length(), m = t.length();int i = 0, j = 0;while (i < n && j < m) {if (s[i] == t[j]) {i++;}j++;}return i == n;}
};

总结

子序列题型,需要十分注意dp数组的设置,是以i - 1为结尾的数组,还是[0-i-1]区间内的数组。取决于是否最后一个元素加入是有前置要求的。

假如最后一个元素是可以直接加入的,例如最大公共子序列,不相交的线等,那么就可以是[0-i- 1]的区间。

但加入最后一个元素加入的话,必须它前面没有元素,或者必须有它前面相邻的元素, 那么就不能是区间了,而需要时以i - 1为结尾。

还需要多加练习,记忆。

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

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

相关文章

【微信小程序实战教程】之微信小程序原生开发详解

微信小程序原生开发详解 微信小程序的更新迭代非常频繁&#xff0c;几乎每个月都会有新版本发布&#xff0c;这就会让初学者感觉到学习的压力和难度。其实&#xff0c;我们小程序的每次版本迭代都是在现有小程序架构基础之上进行更新的&#xff0c;如果想要学好小程序开发技术&…

面试经典 114. 二叉树展开为链表

最近工作越来越难找&#xff0c;裁员越来越懂了&#xff0c;焦虑的睡不着&#xff0c;怎么办呢&#xff0c;只能刷面试题&#xff0c;卷死你们 今天这个题目没刷过&#xff0c;我思考了半天才只能用暴力&#xff0c;后来苦思冥想才想出来简单的方法&#xff0c;废话不多说&…

【机器学习】激活函数:神经网络的灵魂

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 激活函数&#xff1a;神经网络的灵魂什么是激活函数?常见激活函数类型1. Sigmo…

深入了解 JMeter 中的响应断言

JMeter 是一个强大的性能测试工具&#xff0c;能够模拟大量用户并发访问网站或应用程序&#xff0c;以便测试其性能和稳定性。在进行性能测试时&#xff0c;我们需要对响应结果进行断言&#xff0c;以确保应用程序或网站的功能和性能符合预期。 JMeter 提供了一套丰富的响应断…

VINS-FUSION 优化-IMU预积分因子(二)

VINS-FUSION 优化-IMU预积分因子(一)完成了IMU预积分及对于优化变量的全部雅克比矩阵的推导,本文结合VINS-FUSION源码,完成优化-IMU预积分因子的使用。 一、IMU预积分因子雅克比 VINS-FUSION源码中将优化变量分组如下: 1.对i时刻优化变量的雅可比

8.0.32 mysql 配置主从数据库

配置前提&#xff1a; 两台服务器都需要安装同一版本的mysql数据库 我的版本是8.0.32 数据库参数修改 主数据库my.cnf(linux)或my.ini(win)配置&#xff1a; 这里需要注意&#xff1a;server-id必须唯一主从两个库必须要不一样 log_binmysql-bin server-id24 gtid-modeON …

chapter08-面相对象编程的三大特征——封装

1、基础介绍 对电视机的操作就是典型封装 封装的好处&#xff1a;隐藏实现细节&#xff1b;可以对数据进行验证 2、封装的实现 3、入门案例 altinsert&#xff0c;getter and setter&#xff0c;自动插入

生成式人工智能的未来之路:对话系统与自主代理的交汇与展望

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

RAS--APEI 报错解析流程(2)

RAS--APEI 报错解析流程(1) 除了APEI 中除了GHES会记录错误&#xff0c;在Post过程中的错误通常是通过BERT Table汇报 1.BERT Boot Error Record Table is used to report unhandled errors that occurred in a previous boot&#xff0c;it is reported as a ‘one-time polle…

HarmonyOS Next 省市区级联(三级联动)筛选框

效果图 完整代码 实例对象 export class ProvinceBean {id?: stringpid?: stringisSelect?: booleandeep?: objectextName?: stringchildren?: ProvinceBean[] }级联代码 import { MMKV } from tencent/mmkv/src/main/ets/utils/MMKV import { ProvinceBean } from ..…

基于 HTML+ECharts 实现智慧运维数据可视化大屏(含源码)

智慧运维数据可视化大屏&#xff1a;基于 HTML 和 ECharts 的实现 在现代企业中&#xff0c;运维管理是确保系统稳定运行的关键环节。随着数据量的激增&#xff0c;如何高效地监控和分析运维数据成为了一个重要课题。本文将介绍如何利用 HTML 和 ECharts 实现一个智慧运维数据可…

深入理解 Java NIO:ByteBuffer和MappedByteBuffer的特性与使用

目录 前言 ByteBuffer是什么 重要特点 分配缓冲区 读写模式切换 操作文本数据 操作基本数据类型 案例解析-循环输出数据 MappedByteBuffer是什么 MappedByteBuffer 的工作机制 刷盘时机 总结 前言 在深入学习 RocketMQ 这款高性能消息队列框架的源码时&#xff0c…

醒醒,别睡了...讲《数据分析pandas库》了—/—<1>

一、了解pandas No.1 Pandas 是 Python 语言的一个扩展程序库&#xff0c;用于数据分析&#xff0c;是一个强大的分析结构化数据的工具集&#xff0c;基础是Numpy库&#xff0c;可以去参考前面所讲的课。&#xff08;提供高性能的矩阵运算&#xff09; No.2 应用 &#xff1a;P…

vue上传Excel文件并直接点击文件列表进行预览

本文主要内容&#xff1a;用elementui的Upload 组件上传Excel文件&#xff0c;上传后的列表采用xlsx插件实现点击预览表格内容效果。 在项目中可能会有这样的需求&#xff0c;有很多种方法实现。但是不想要跳转外部地址&#xff0c;所以用了xlsx插件来解析表格&#xff0c;并展…

Docker安装kkFileView实现在线文件预览

kkFileView为文件文档在线预览解决方案,该项目使用流行的spring boot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等 官方文档地址:https://kkview.cn/zh-cn/docs/production.html 一、拉取镜像 do…

1 深度学习网络DNN

代码来自B站up爆肝杰哥 测试版本 import torch import torchvisiondef print_hi(name):print(fHi, {name}) if __name__ __main__:print_hi(陀思妥耶夫斯基)print("HELLO pytorch {}".format(torch.__version__))print("torchvision.version:", torchvi…

用在ROS2系统中保持差速轮方向不变的PID程序

在ROS 2中&#xff0c;为了保持差速轮机器人的方向不变&#xff0c;通常需要使用PID&#xff08;Proportional Integral Derivative&#xff09;控制器来控制机器人的角速度。PID控制器可以帮助调整机器人的角速度&#xff0c;以维持其朝向不变。 下面是一个简单的ROS 2节点示…

使用el-table的案例小结——包含跨页多选、双击行、分页器、编辑\删除行、动态根据分页生成序号

首先看一下业务需求 需要实现跨页多选&#xff0c;双击行的时候弹出编辑对话框&#xff0c;对每行可以进行编辑和删除&#xff0c;实现分页器。 如果还没在项目中配置element-plus的可以参考文章 从零开始创建vue3项目——包含项目初始化、element-plus、eslint、axios、router…

vue import from

vue import from 导入文件&#xff0c;从XXXX路径&#xff1b;引入文件 import xxxx from “./minins/resize” import xxxx from “./minins/resize.js” vue.config.js 定义 : resolve(src)&#xff1b;就是指src 目录 import xxxx from “/utils/auth” im…

【C++初阶】string类

【C初阶】string类 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;C&#x1f96d; &#x1f33c;文章目录&#x1f33c; 1. 为什么学习string类&#xff1f; 1.1 C语言中的字符串 1.2 实际中 2. 标准库中的string类 2.1 string类 2.…