【算法练习Day45】最长公共子序列不相交的线最大子数组和

在这里插入图片描述

​📝个人主页:@Sherry的成长之路
🏠学习社区:Sherry的成长之路(个人社区)
📖专栏链接:练题
🎯长路漫漫浩浩,万事皆有期待

文章目录

  • 最长公共子序列
  • 不相交的线
  • 最大子数组和
  • 总结:

前两道题思路是一模一样的,但是需要认真理解,最后一道虽然思路不算难,但是需要注意的细节一点不少。

最长公共子序列

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

最长公共子序列,与上一期最后一道的区别在于本题要求的是两个数组的可以删除中间数据的最长公共的部分。是删除中间部分的多于元素后,在不改变数据顺序情况下得到的最长公共子序列,

也就是要把求两数组的最长子序列的题,和求不连续最长子序列的题结合在一起的考题。

dp数组的含义:对于两个数组求子序列问题,通常我们要设立二维数组来辅助解题,二维数组的含义依然是到以i-1和j-1下标的对应数据 最长公共子序列为多长。是以i-1和j-1对应的下标对应的数据为结尾,是因为为了方便初始化,不懂得可以去看我上一期的文章。

递推公式:递推公式是有讲究的,这也是与上一期的最后一题的差别所在,求可以删除中间数据拼成的序列,也就是求非连续的子序列的问题,一定要用双for循环来遍历,

if(nums1【i-1】==nums2【j-1】)dp【i】【j】=dp【i-1】【j-1】+1

这也是之前我们讲过的递推公式,因为找到了一个相等的字符,所以就是上一个位置+1的长度。

那说回来,如果两个字符不相等呢?又如何用代码来表示两个数组之间的删除中间数据呢?这也就有了第二个递推公式

else dp【i】【j】=max(dp【i-1】【j】,dp【i】【j-1】)

也就是说如果两个数据此时不相等,那么它这个位置填入的长度应该就是dp【i-1】【j】,dp【i】【j-1】取最大值,为什么是这样呢?我们可以依照所给案例分析,abcde和ace,我们假设现在遍历到这两个数组的第2个位置,很显然2下标下c和e是不相等的,那么abc和ace的两部分最长公共子序列多长呢?既然知道这两个位置一定不等,那么就有两种情况,可能最大子序列存在于abc和ac的情况,也可能最大子序列存在于ab和ace的情况,这两种情况的最大子序列中,我们取最大值,也就是当前遍历的两字符不等的情况。

dp数组的初始化:数组的初始化也很简单,因为我们上一期已经讲过,对于这种二维数组的定义为i-1和j-1的含义时,第一行和第一列没有意义是非法状态,所以都初始化为0,而其他部分初始化什么值不重要,都会被递推公式所覆盖。

遍历顺序:从左到右,从上到下。

class Solution {
public:int longestCommonSubsequence(string text1, string text2) {vector<vector<int>>dp(text1.size()+1,vector<int>(text2.size()+1,0));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()];}
};

代码就是这样了,实际上也不是很难,但是那个else也就是字符不相等的情况,怎么去处理,相信对于第一次做这道题的朋友来说,还是很懵b的。

不相交的线

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

这道题和第一道题思路一模一样,为什么这么说呢?它是求两数组相等数字俩俩连线,且不能相交,其实就是求两个数组的最长递增子序列,有多长,有多长就有几个连线。至于题中说的一个数据只能被连一次,那是一定的。例如第一个数组的某数据和第二个数组的连续两个数据都相等,但是根据递推公式它们的连线条数是根据之前连线条数有关,也就是说如果之前没有一样的数据,连线条数是0,那么dp【i-1】【j-2】和dp【i-1】【j-1】不也都是0吗,所以得到的连线条数都是1。这里你可以随便举例子,即使之前已经有一条连线,也仅仅只有dp【i】【j】能够变成2,而另一个也能够与第一个数组相等数据那个,是由dp【i-1】【j-2】推出来的,画dp数组就会知道,最大数都集中在斜线上,从左上角到右上角那条斜线,主导着大值。所以有时候打印dp数组还是很重要的。

class Solution {
public:int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {vector<vector<int>>dp(nums1.size()+1,vector<int>(nums2.size()+1,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]);}}return dp[nums1.size()][nums2.size()];}
};

好了,经过了一些列的分析我直接给出代码,代码和上一道题一模一样。

至于为什么这里的二维数组我们不需要result来存取最大值,然后输出,为什么这里的dp数组最后一位置是最大值呢?这是因为else那一条语句的缘故,因为我们求得是非连续的,而我们这样写递推公式dp【i】【j】会一直保留着之前的最长子序列的长度,自然也就不用result来存取最大值了。

最大子数组和

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

这道题以前讲贪心算法时候,做过一次,我们再用动态规划思想,做一次,解题的思路不是很难,但是细节需要注意。起初我在想这道题的解法时候,递推公式也像上面的题一样,写成两个,但后来遇到全负数的数组却无法解出。

dp数组含义:dp数组的含义代表截止到i的连续的最大子数组和,根据dp数组的含义,也意味着我们这时候需要result来存储最大的和了。

递推公式:递推公式实际上是很简单的一句代码,但是由于前面两道题的启发,我有点想复杂了,

dp【i】=max(dp【i-1】+nums【i】,nums【i】)

其实看过贪心的朋友,再看这种思路反而应该更好想明白,dp数组由两个方向可以推出来,一个是前面的连续数组相加的和加上当前遍历到的数据做和,另一个是只有当前的数据,它们做一个比较,取较大者,其实仔细想想这样无论数组是否是纯负数都能得到解决了,起初的想法是result赋值为最小值,然后和result比较,再配上我那个ifelse语句,出了不少差错。

初始化和遍历顺序都是千篇一律这里不做讲解了。

class Solution {
public:int maxSubArray(vector<int>& nums) {vector<int>dp(nums.size(),0);if(nums.size()==0)return 0;dp[0]=nums[0];int result=dp[0];for(int i=1;i<nums.size();i++){dp[i]=max(dp[i-1]+nums[i],nums[i]);result=max(result,dp[i]);}return result;}
};

动态规划类题目,都是代码简单,思路难想,而且有的时候代码也有很多要注意的细节,要多练习。

总结:

今天我们完成了最长公共子序列、不相交的线、最大子数组和三道题,相关的思想需要多复习回顾。接下来,我们继续进行算法练习。希望我的文章和讲解能对大家的学习提供一些帮助。

当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~

在这里插入图片描述

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

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

相关文章

浅浅地优化下视频流播放体验

作者&#xff1a;唐子玄 这一篇将从零开始&#xff0c;一步步解决如下这些问题&#xff1a;如何播放单个视频&#xff1f;如何将播放器模块化&#xff1f;如何实现视频流&#xff1f;如何优化视频播放内存&#xff1f;如何优化视频流播放体验&#xff1f; 播放视频 ExoPlayer…

基于Docker容器DevOps应用方案

文章目录 基于docker容器DevOps应用方案环境基础配置1.所有主机永久关闭防火墙和selinux2.配置yum源3.docker的安装教程 配置主机名与IP地址解析部署gitlab.server主机1.安装gitlab2.配置gitlab3.破解管理员密码4.验证web页面 部署jenkins.server主机1.部署tomcat2.安装jenkins…

蓝桥杯每日一题2023.11.10

“蓝桥杯”练习系统 (lanqiao.cn) 题目描述 题目分析 对于此题&#xff1a;我们看到题目要求尽可能大&#xff0c;会联想到二分&#xff0c;注意切出的一定为正方形&#xff0c;其能切出的个数为(h[i] / x) * (w[i] / x)&#xff0c;将所有的个数与要求的个数进行对比&#x…

阿里云-maven私服idea访问私服与组件上传

1.进入aliyun制品仓库 2. 点击 生产库-release进入 根据以上步骤修改本地 m2/setting.xml文件 3.pom.xml文件 点击设置获取url 4. idea发布组件

Day26力扣打卡

打卡记录 搜索旋转排序数组&#xff08;二分&#xff09; 链接 class Solution {int findMin(vector<int> &nums) {int left -1, right nums.size() - 1; // 开区间 (-1, n-1)while (left 1 < right) { // 开区间不为空int mid left (right - left) / 2;if…

[NLP] 使用Llama.cpp和LangChain在CPU上使用大模型

一 准备工作 下面是构建这个应用程序时将使用的软件工具: 1.Llama-cpp-python 下载llama-cpp, llama-cpp-python [NLP] Llama2模型运行在Mac机器-CSDN博客 2、LangChain LangChain是一个提供了一组广泛的集成和数据连接器&#xff0c;允许我们链接和编排不同的模块。可以常…

threejs(11)-精通着色器编程(难点)2

一、shader着色器编写高级图案 小日本国旗 precision lowp float; varying vec2 vUv; float strength step(0.5,distance(vUv,vec2(0.5))0.25) ; gl_FragColor vec4(strength,strength,strength,strength);绘制圆 precision lowp float; varying vec2 vUv; float strength 1…

Unity 一些内置宏定义

在Unity中&#xff0c;有一些内置的宏定义可用于不同的平台。以下是一些常见的平台内置宏定义&#xff1a; 1、UNITY_EDITOR&#xff1a;在Unity编辑器中运行。 2、UNITY_EDITOR_WIN&#xff1a;在Unity编辑器运行在Windows操作系统时被定义。 3、UNITY_STANDALONE&#xff1a…

深度学习 python opencv 火焰检测识别 火灾检测 计算机竞赛

文章目录 0 前言1 基于YOLO的火焰检测与识别2 课题背景3 卷积神经网络3.1 卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV54.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 数据集准备5.1 数…

【Linux】文件重定向以及一切皆文件

文章目录 前言一、重定向二、系统调用dup2三、重定向的使用四、一切皆文件 前言 Linux进程默认情况下会有3个缺省打开的文件描述符&#xff0c;分别是标准输入0&#xff0c; 标准输出1&#xff0c; 标准错误2&#xff0c; 0,1,2对应的物理设备一般是&#xff1a;键盘&#xff…

论文笔记:AttnMove: History Enhanced Trajectory Recovery via AttentionalNetwork

AAAI 2021 1 intro 1.1 背景 将用户稀疏的轨迹数据恢复至细粒度的轨迹数据是十分重要的恢复稀疏轨迹数据至细粒度轨迹数据是非常困难的 已观察到的用户位置数据十分稀疏&#xff0c;使得未观察到的用户位置存在较多的不确定性真实数据中存在大量噪声&#xff0c;如何有效的挖…

C语言--前置++与后置++

:自增1 注意区分前置和后置 前置&#xff1a;先&#xff0c;后使用 后置&#xff1a;先使用&#xff0c;后 --:自减1 注意区分前置和后置 前置&#xff1a;先-- &#xff0c;后使用 后置&#xff0c;先使用&#xff0c;后-- int main() {int i 10;//int j i;//前置,先…