代码随想录刷题day53|最长公共子序列不相交的线最大子序和

文章目录

  • day53学习内容
  • 一、最长公共子序列
    • 1.1、动态规划五部曲
      • 1.1.1、 确定dp数组(dp table)以及下标的含义
      • 1.1.2、确定递推公式
      • 1.1.3、 dp数组如何初始化
      • 1.1.4、确定遍历顺序
      • 1.1.5、输出结果
    • 1.2、代码
  • 二、不相交的线
    • 2.1、动态规划五部曲
      • 2.1.1、 确定dp数组(dp table)以及下标的含义
      • 2.1.2、确定递推公式
      • 2.1.3、 dp数组如何初始化
      • 2.1.4、确定遍历顺序
      • 2.1.5、输出结果
    • 2.2、代码
  • 三、最大子序和
    • 3.1、动态规划五部曲
      • 3.1.1、 确定dp数组(dp table)以及下标的含义
      • 3.1.2、确定递推公式
      • 3.1.3、 dp数组如何初始化
      • 3.1.4、确定遍历顺序
      • 3.1.5、输出结果
    • 3.2、代码
  • 总结
    • 1.感想
    • 2.思维导图


day53学习内容

day53主要内容

  • 最长公共子序列
  • 不相交的线
  • 最大子序和

声明
本文思路和文字,引用自《代码随想录》


一、最长公共子序列

1143.原题链接

1.1、动态规划五部曲

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

  • dp[i][j] 表示字符串 text1 的前 i 个字符和字符串 text2 的前 j 个字符的最长公共子序列的长度。

1.1.2、确定递推公式

基本思路
我们可以根据两个字符串中当前字符是否相等,采取不同的策略来更新 dp 表。
与最长公共子数组(或子串)不同,子序列不要求元素在原字符串中是连续的,只要求它们保持相对顺序即可。

推导状态转移方程

  1. 字符匹配的情况
    text1[i-1] == text2[j-1] 时,这意味着这两个字符可以成为目前为止考虑的字符串的公共子序列的一部分。因此,这两个字符将增加公共子序列的长度,即
dp[i][j]=dp[i−1][j−1]+1

这个方程表明,text1 的前 i 个字符和 text2 的前 j 个字符的最长公共子序列可以通过在它们的前 i-1 个字符和前 j-1 个字符的最长公共子序列的基础上添加这两个匹配的字符来得到。

  1. 字符不匹配的情况
    text1[i-1] != text2[j-1] 时,最长公共子序列不能同时包括这两个字符。因此,有以下两种可能性:
    • 忽略 text1 的当前字符 i-1,只考虑 text1 的前 i-1 个字符和 text2 的前 j 个字符。
    • 忽略 text2 的当前字符 j-1,只考虑 text1 的前 i 个字符和 text2 的前 j-1 个字符。
      这两种情况下的最长公共子序列的长度将是:
dp[i][j]=max(dp[i−1][j],dp[i][j−1])

这个方程表明,当前的 dp[i][j] 应取前面两种情况中更长的子序列长度。

1.1.3、 dp数组如何初始化

  • dp[0][x]dp[x][0] 应该初始化为 0,因为一个长度为 0 的字符串与任何字符串的最长公共子序列长度都是 0。
  • 或者这句话看不懂,就画个图。。。看一下推导的方向就明白了
    在这里插入图片描述
    图引用自卡尔的视频。

https://www.bilibili.com/video/BV1ye4y1L7CQ/?spm_id_from=pageDriver&vd_source=266f115062b99cd2d8e5185add0b8cc9

1.1.4、确定遍历顺序

从小到大遍历

1.1.5、输出结果

  • return dp[text1.length()][text2.length()]; 最后,dp 数组的最后一个元素(即 dp[text1.length()][text2.length()])包含了整个 text1text2 的最长公共子序列的长度。

1.2、代码

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        // 创建二维数组dp,大小为text1长度+1和text2长度+1
        int[][] dp = new int[text1.length() + 1][text2.length() + 1];

        // 遍历text1的每一个字符
        for (int i = 1; i <= text1.length(); i++) {
            char char1 = text1.charAt(i - 1); // 获取text1的第i-1个字符
            // 遍历text2的每一个字符
            for (int j = 1; j <= text2.length(); j++) {
                char char2 = text2.charAt(j - 1); // 获取text2的第j-1个字符

                // 如果两个字符相同
                if (char1 == char2) {
                    // 如果当前的两个字符相同,则当前dp[i][j]应基于之前的dp[i-1][j-1]的值加1
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    // 如果两个字符不同,选择之前两种情况的较大者作为当前dp[i][j]的值
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }

        // 返回数组的最后一个元素,即为text1和text2的最长公共子序列长度
        return dp[text1.length()][text2.length()];
    }
}

二、不相交的线

1035.原题链接

它实质上和最长公共子序列(LCS)问题相同,只是在不同的上下文中应用。在这个问题中,我们要在两个数组中找到最多的对应数字(或线),使得这些数字的顺序在两个数组中保持一致,但不必连续。

2.1、动态规划五部曲

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

  • 其中 dp[i][j] 代表考虑 nums1 的前 i 个元素和 nums2 的前 j 个元素时的最大不相交线数(或最长公共子序列的长度)。

2.1.2、确定递推公式

  • for (int i = 1; i <= len1; i++):外层循环遍历 nums1
  • for (int j = 1; j <= len2; j++):内层循环遍历 nums2
    • if (nums1[i - 1] == nums2[j - 1]):如果当前考虑的两个元素相等,表示可以在此基础上形成一个新的对应线,所以 dp[i][j] = dp[i - 1][j - 1] + 1;。这意味着我们在之前的最大对应线数的基础上增加一条新的线。
    • else:如果当前的两个元素不相等,则我们需要决定是跳过 nums1 的当前元素还是 nums2 的当前元素,以保持最大的对应线数。因此,dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); 选择这两种情况中较大的一个。

2.1.3、 dp数组如何初始化

根据前面的分析。dp 表的最后一个元素就是两个数组中可以形成的最大不相交线数,这等同于最长公共子序列的长度。所以初始化逻辑和上面那题是一样的,这里不再赘述了。

2.1.4、确定遍历顺序

从小到大遍历

2.1.5、输出结果

  • return dp[len1][len2]; 动态规划表的最后一个元素包含了整个 nums1nums2 可以形成的最大不相交线数。

2.2、代码

class Solution {
    // maxUncrossedLines 方法用来计算两个数组间的最大未交叉线数
    public int maxUncrossedLines(int[] nums1, int[] nums2) {
        // len1 和 len2 分别是两个数组的长度
        int len1 = nums1.length;
        int len2 = nums2.length;
        // dp 数组用于存储动态规划的中间结果
        int[][] dp = new int[len1 + 1][len2 + 1];

        // 外层循环遍历 nums1
        for (int i = 1; i <= len1; i++) {
            // 内层循环遍历 nums2
            for (int j = 1; j <= len2; j++) {
                // 如果当前两个数组的元素相等,更新 dp 数组的值
                if (nums1[i - 1] == nums2[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    // 如果不相等,取两种情况的较大值,即不包含当前 nums1 的元素或不包含当前 nums2 的元素
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }

        // 返回 dp 数组右下角的值,即为最大未交叉线数
        return dp[len1][len2];
    }
}

三、最大子序和

53.原题链接

3.1、动态规划五部曲

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

  • dp[i] 表示以第 i 个元素结尾的最大子数组和。

3.1.2、确定递推公式

  • 从数组的第二个元素开始遍历(即i=1)。
  • 对于每个元素nums[i],更新dp[i]。这里的转移方程是:
    • dp[i] = Math.max(dp[i-1] + nums[i], nums[i])
    • 这个方程的意思是,考虑到第i个元素时,最大子数组和可以是:
      • dp[i-1] + nums[i](即包含之前的最大子数组和再加上当前元素nums[i]),或者
      • nums[i]本身(即从新开始计数,只取当前元素,这种情况适用于dp[i-1]是负数,不如放弃之前的累计,重新开始)。
  • 同时更新结果res,如果dp[i]比当前的res还要大,就用dp[i]更新res

3.1.3、 dp数组如何初始化

dp[0]即为nums[0],因为第一个元素前面没有其他元素,所以它自身就是一个子数组。

3.1.4、确定遍历顺序

从小到大遍历

3.1.5、输出结果

最后返回 res,它存储的是整个数组的最大子数组和。

3.2、代码

class Solution {
    public int maxSubArray(int[] nums) {
        // 如果数组为空,则直接返回0(通常情况下,这里可以根据题意返回负无穷或抛出异常)
        if (nums.length == 0) {
            return 0;
        }

        // res用来存储最终的最大子数组和,初值设为数组的第一个元素
        int res = nums[0];
        // dp数组用于动态规划存储到当前元素为止的最大子数组和,dp[0]自然是第一个元素
        int[] dp = new int[nums.length];
        dp[0] = nums[0];

        // 从数组的第二个元素开始遍历
        for (int i = 1; i < nums.length; i++) {
            // 动态规划的转移方程:比较“继续当前子数组”与“从新的位置开始”
            dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
            // 更新全局的最大子数组和
            res = Math.max(res, dp[i]);
        }
        // 返回计算得到的最大子数组和
        return res;
    }
}

总结

1.感想

  • 补周六的进度,冲

2.思维导图

本文思路引用自代码随想录,感谢代码随想录作者。

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

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

相关文章

【Git】Git的安装与常用命令

Git的安装与常用命令 一、Git的安装 &#xff08;一&#xff09;下载 官网下载&#xff1a;https://git-scm.com/downloads 镜像网站&#xff1a;https://registry.npmmirror.com/binary.html?pathgit-for-windows/ &#xff08;二&#xff09;安装 双击安装&#xff0c…

智能客服系统如何高效分配会话的实用指南

面对现在快节奏的商业市场&#xff0c;能否快速地把握住商机成为了企业制胜的关键&#xff0c;所以很多企业都想要一个可以快速响应客户需求的工具来帮助他们实现更高效的转化。如果能够有一个可以智能识别并自动将客户分配给合适客服的系统&#xff0c;来保证每个客户都能享受…

抖音扫码登录

抖音扫码登录&#xff0c;ck可以点赞关注上传视频 主要涉及参数: bd_ticket_guard_client_data bd_ticket_guard_server_data bd_ticket_guard_ree_public_key bd_ticket_crypt_cookie x–secadk–csrf–token req_sign abogus ts_sign ticket {"is_digg":…

从工程师到医疗高管,复旦MBA助我实现职场飞跃 | 校友故事

2月12日&#xff0c;英国《金融时报》&#xff08;FT&#xff09;发布2024年全球MBA项目百强榜单&#xff0c;复旦大学MBA项目位列全球第27位&#xff0c;并在多个分指标上位居全球前列。其中“职业服务”和“ESG与零排放教学”蝉联亚洲第1、“薪酬增长率”全球第2、“职业成长…

“智能医疗新纪元:机器学习在医疗健康领域的创新应用“

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

[docker] 核心知识 - 容器/镜像的管理和操作

[docker] 核心知识 - 容器/镜像的管理和操作 想要查看完整的指令&#xff0c;可以通过 docker --help 列举所有的指令&#xff0c;这里会提到一些比较常用的核心指令 查看容器的状态 这个应该是最常用的指令&#xff0c;语法为 docker ps&#xff0c; ps 为 process status …

java:多线程解决生产者消费者问题

生产者消费者问题 生产者消费者问题&#xff0c;也称有限缓冲问题&#xff0c;是一个多线程同步问题的经典案例。该问题描述了共享固定大小缓冲区的两种线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中…

【Qt 学习笔记】Qt常用控件 | 按钮类控件Radio Button的使用及说明

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 按钮类控件Radio Button的使用及说明 文章编号&#xff…

【机器学习】机器学习创建算法第6篇:线性回归,学习目标【附代码文档】

机器学习&#xff08;算法篇&#xff09;完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;机器学习算法课程定位、目标&#xff0c;K-近邻算法定位,目标,学习目标,1 什么是K-近邻算法,1 Scikit-learn工具介绍,2 K-近邻算法API。K-近邻算法&#xff0c;1.4 …

云服务器降价,阿里腾讯华为京东云优惠价格表整理

现在租一个服务器多少一个月&#xff1f;优惠价格低至3.8元1个月&#xff0c;租用一个月云服务器收费价格表&#xff1a;阿里云和腾讯云2核2G3M服务器优惠价格61元一年&#xff0c;折合一个月5元&#xff0c;京东云轻量云主机5.8元一个月&#xff0c;华为云服务器优惠价格3.8元…

如何落地一个FaaS平台?

简介&#xff1a; 函数即服务&#xff08;FaaS&#xff09;作为云计算 2.0 时代重要的发展方向&#xff0c;能够从工程效率、可靠性、性能、成本等方面给开发者带来巨大的价值&#xff0c;尤其是能够极大地提升研发效率。因此&#xff0c;拥抱FaaS成为开发者关心的重要技术领域…

【Java】maven的生命周期和概念图

maven的生命周期&#xff1a; 在maven中存在三套"生命周期"&#xff0c;每一套生命周期,相互独立,互不影响的,但是中同一套生命周期里,执行后面的命令会自动先执行前面的命令 CleanLifeCycle&#xff1a;清理的生命周期 clean defaultLifeCycle&#xff1a;默认的…

YashanDB亮相数据技术嘉年华精彩不断

4月12-13日&#xff0c;由墨天轮数据社区和中国数据库联盟&#xff08;ACDU&#xff09;主办的第十三届数据技术嘉年华 &#xff08;DTC 2024&#xff09;在北京召开。崖山数据库系统YashanDB受邀亮相&#xff0c;多维度展示了YashanDB的独特技术、创新成果与行业应用。 数据库…

大话设计模式之享元模式

享元模式是一种结构型设计模式&#xff0c;旨在有效地支持大量细粒度的对象共享&#xff0c;从而减少内存消耗和提高性能。 在享元模式中&#xff0c;对象分为两种&#xff1a;内部状态&#xff08;Intrinsic State&#xff09;和外部状态&#xff08;Extrinsic State&#xf…

代码随想录阅读笔记-回溯【复原IP地址】

题目 给定一个只包含数字的字符串&#xff0c;复原它并返回所有可能的 IP 地址格式。 有效的 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。 例如&#xff1a;"0.1.2.201…

D3-八数码

D3-八数码 题目描述解题思路代码如下 题目描述 解题思路 本题若直接在3*3网格中思考较为困难&#xff0c;可以转换为一维的字符串&#xff0c;在一维字符串中考虑较为简单&#xff0c;要注意本题中两个字符交换位置时只能是x和另外字符交换&#xff0c;本题另外一个难点在于如何…

TypeScript系列之-深度理解基本类型画图讲解

JS的类型(8)&#xff1a; null undefined string number boolean bigint symbol object&#xff08;含 Array, Function,Date.....&#xff09; TS的类型(87): 以上所有&#xff0c;加上 void, never, enum, unknown, any 再加上自定义类型 type interface 上一节我们说…

判断IQ水平-第12届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第50讲。 判断IQ水平&#…

利用栈删除数组中重复元素

先将数据排序&#xff08;降序或升序&#xff09; 建立一个“栈”&#xff0c;三种情况&#xff1a; 1.栈为空&#xff1a;压入一个元素 2.栈不为空 且 栈顶元素不等于将入栈元素&#xff1a;压入一个元素 3.栈不为空 且 栈顶元素等于将入栈元素&#xff1a;删除将压入元素…

SCI 四区(JEI)投稿到录用过程中的经历和心得体会

计算机视觉领域中&#xff0c;包含目标检测、三维重建、语义分割、图像分类等分支。其中&#xff0c;目标检测分支最卷&#xff0c;你知道的&#xff0c;没有背景和资源&#xff0c;发一篇SCI属实不易。本篇博客详细介绍本人投稿到录用过程中的经历和心得。 目录 1. 硬件资源落…