代码随想录算法训练营第五十三天 | LeetCode 1143. 最长公共子序列、1035. 不相交的线、53. 最大子数组和

news2024/11/24 21:08:22

代码随想录算法训练营第五十三天 | LeetCode 1143. 最长公共子序列、1035. 不相交的线、53. 最大子数组和

文章链接:最长公共子序列、不相交的线、最大子数组和
视频链接:最长公共子序列、不相交的线、最大子数组和

1. LeetCode 1143. 最长公共子序列

1.1 思路

  1. 在718. 最长重复子数组中的重复子数组要求是连续的,本题也是要求重复子数组,要按照数组的顺序,虽然可以不连续。本题用动态规划解决的难点在于如何去表示这两个数组进行比较的状态,在718. 最长重复子数组中我们是用二维数组比较的,横向表示 nums1,纵向表示 nums2

  2. dp 数组及其下标的含义:dp[i][j]:长度以 [0,i-1] 的 nums1 和长度以 [0,j-1] 的 nums2 的最长公共子序列为 dp[i][j]。为什么定义 i-1 而不是 i 呢?其实也可以,但是那么写可以精简一些初始化的地方,如果写成 i 就需要对第一行和列初始化

  3. 递推公式:我们肯定要比较元素是否相同,即 if(nums1[i-1]==nums2[j-1])dp[i][j]=dp[i-1][j-1]+1,就是在这基础上加 1。如果不相同,即 else dp[i][j]=Math.max(dp[i][j-1],dp[i-1][j])
    在这里插入图片描述

  4. dp 数组的初始化:从递推公式可看出,i,j 是需要这三个方向推导出来的,因此要把第一行和列初始化了,即 dp[0][j] 和 dp[i][0],那么根据 dp 数组的含义,是跟 [0,i-1] 和 [0,j-1] 比较,本来就是 0 了再减 1 就成负的,就是一个空的字符串的,那么即 nums1 和空的字符串的最长公共子序列以及 nums2 和空的字符串的最长公共子序列就应该是 0,因此都初始化为 0。而其余下标会被其他位置覆盖,就也初始化为 0 即可
    在这里插入图片描述

  5. 遍历顺序:根据上图的方向,因此是从左往右遍历。for(int i=1;i<=nums1.length;i++)for(int j=1;j<=nums2.length;j++)为什么从 1 开始,因为第一行和列都初始化了,并且递推公式也是从 i-1 和 j-1 推导来的,因此从 1 开始,为什么需要等于号,因为根据 dp 数组的含义,我们的数组范围是 [0,i-1] 和 [0,j-1],只有去等于号了,才能取到数组的最后一个元素,而我们定义 dp 数组时也应该定义个长度为 nums1.length+1,nums2.length+1。最终结果存在 dp[nums1.length][nums2.length]

  6. 打印 dp 数组:用于 debug

1.2 代码

/*
	二维dp数组
*/
class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        // char[] char1 = text1.toCharArray();
        // char[] char2 = text2.toCharArray();
	// 可以在一開始的時候就先把text1, text2 轉成char[],之後就不需要有這麼多爲了處理字串的調整
	// 就可以和卡哥的code更一致
 	
        int[][] dp = new int[text1.length() + 1][text2.length() + 1]; // 先对dp数组做初始化操作
        for (int i = 1 ; i <= text1.length() ; i++) {
            char char1 = text1.charAt(i - 1);
            for (int j = 1; j <= text2.length(); j++) {
                char char2 = text2.charAt(j - 1);
                if (char1 == char2) { // 开始列出状态转移方程
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        return dp[text1.length()][text2.length()];
    }
}

2. LeetCode 1035. 不相交的线

2.1 思路

  1. 本题要在两个数组中找到相同的数字然后连成线,并且线之间不能相交。本题很容易陷进去怎么判断线不能相交的问题。我们要找的是相同元素,同时保证数组顺序不变,其实也是求子序列问题。举例如果两个数组是 [1,2][2,1] 那这是相同子序列吗?不是,这里相同子序列只能是 1 和 1 或者 2 和 2。那本题让我们找最多条可连接的线,就相当于找最长公共子序列,那和1143. 最长公共子序列就一样了。
  2. 因此本题的解题逻辑和我在1143. 最长公共子序列这题的是一样的。

2.2 代码

  class Solution {
    public int maxUncrossedLines(int[] nums1, int[] nums2) {
        int len1 = nums1.length;
        int len2 = nums2.length;
        int[][] dp = new int[len1 + 1][len2 + 1];

        for (int i = 1; i <= len1; i++) {
            for (int j = 1; j <= len2; j++) {
                if (nums1[i - 1] == nums2[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 dp[len1][len2];
    }
}

3. LeetCode 53. 最大子数组和

3.1 思路

  1. 本题是给一个数组求最大子序和,指的就是子数组的最大和,子数组就是连续的子序列,求出和是在这个数组的子数组中最大的。本题可以暴力也可以贪心,但这里用动态规划做。
  2. dp 数组及其下标的含义:dp[i]:以 i 为结尾(即元素 nums[i])的最大连续子序列的和为 dp[i]
  3. 递推公式:有两种情况,1 是延续着前面的子序列的和继续累加;2 是不延续前面的子序列,从现在的位置重新开始算。第 1 种情况,nums[i] 前面的和就是以 i-1 为结尾的最大子序列和 dp[i-1],即 dp[i-1]+nums[i],第 2 种情况就是不要前面的了,即 nums[i]。因此 dp[i]=Math.max(dp[i-1]+nums[i],nums[i])
  4. dp 数组的初始化:dp[i] 是依赖 dp[i-1] 的,源头是 dp[0],因此初始化为 nums[0],即以第一个元素为结尾的最大子序列和,非 0 下标会被覆盖,因此默认初始化为 0 即可
  5. 遍历顺序:按照递推公式就是从前往后遍历,for(int i=1;i<nums.length;i++)从 1 开始是因为 0 位置已经初始化了,结果是整个 dp 数组的最大值,用 if(result<=dp[i])result=dp[i],而不是 dp[nums.length-1] 的位置,因为未必是以最后一个元素为结尾的最长子序列和最大。
  6. 打印 dp 数组:用于 debug

3.2 代码

/**
     * 1.dp[i]代表当前下标对应的最大值
     * 2.递推公式 dp[i] = max (dp[i-1]+nums[i],nums[i]) res = max(res,dp[i])
     * 3.初始化 都为 0
     * 4.遍历方向,从前往后
     * 5.举例推导结果。。。
     *
     * @param nums
     * @return
     */
    public static int maxSubArray(int[] nums) {
        if (nums.length == 0) {
            return 0;
        }

        int res = nums[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 = res > dp[i] ? res : dp[i];
        }
        return res;
    }

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

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

相关文章

WMS系统出库管理:功能、流程与优势

一、WMS系统出库管理概述 WMS系统是一种用于仓库管理的信息系统&#xff0c;它涵盖了从货物入库、在库管理到出库的全过程。在WMS系统中&#xff0c;出库管理是非常重要的一环&#xff0c;它涉及到的功能包括订单处理、拣货、打包、发货等。通过WMS系统的出库管理&#xff0c;…

世界互联网大会|美创科技新一代 数据安全管理平台,携五大新特性发布亮相

11月7日&#xff0c;2023年世界互联网大会“互联网之光”博览会在浙江乌镇开幕。今年是博览会办展第十年&#xff0c;重点突出国际性、创新性、引领性。在新产品新技术发布活动中&#xff0c;美创科技全新升级的新一代 数据安全管理平台&#xff08;简称&#xff1a;DSM Cloud&…

SaaS 电商设计 (四) 如何做大促压测

一.背景&目标 1.1 常见的压测场景 电商大促:一众各大厂的促销活动场景,如:淘宝率先推出的天猫双11,而后京东拉出的京东 618 .还是后续陆陆续续的一些年货节, 3.8 女神节等等.都属于一些常规的电商大促 票务抢购:常见的如承载咱们 80,90 青春回忆的 Jay 的演唱会,还有普罗…

基于Rabbitmq和Redis的延迟消息实现

1 基于Rabbitmq延迟消息实现 支付时间设置为30&#xff0c;未支付的消息会积压在mq中&#xff0c;给mq带来巨大压力。我们可以利用Rabbitmq的延迟队列插件实现消息前一分钟尽快处理 1.1定义延迟消息实体 由于我们要多次发送延迟消息&#xff0c;因此需要先定义一个记录消息…

小程序与公众号下发统一消息接口返回45109

根据微信官方通告&#xff0c;自 2023 年 9 月 20 日起&#xff0c;下发统一消息接口将被收回&#xff0c;返回45109。链接见 小程序与公众号下发统一消息接口调整通知 | 微信开放社区各位开发者&#xff1a;下发统一消息 接口曾支持小程序与公众号统一的模板消息下发。由于小程…

虹科示波器 | 汽车免拆检修 | 2014款保时捷卡宴车行驶中发动机偶尔自动熄火

一、故障现象 一辆2014款保时捷卡宴车&#xff0c;搭载4.8L自然吸气发动机&#xff0c;累计行驶里程约为10.3万km。车主反映&#xff0c;行驶中发动机偶尔自动熄火&#xff0c;尤其在减速至停车的过程中故障容易出现。 二、故障诊断 接车后路试&#xff0c;确认故障现象与车主所…

DTC Network旗下代币DSTC大蒜头即将上线,市场热度飙升

全球数字资产领导者DTC Network宣布其代币DSTC&#xff08;大蒜头&#xff09;即将于近期上线&#xff0c;引发市场广泛关注。DTC Network以其创新性的区块链技术和多维度的网络构建&#xff0c;致力于打造一个融合Web3.0、元宇宙和DAPP应用的去中心化聚合公共平台&#xff0c;…

Shiro快速入门之二

一、前言 Shiro快速入门之一 介绍了Shiro三大核心组件&#xff0c;四大核心功能&#xff0c;以及一个简单的Test Demo&#xff0c;接下来两篇我会用一个比较完整的例子来讲述Shiro的认证及授权是怎么做的&#xff0c;本篇侧重于介绍认证的过程 二、Shiro认证例子 1、例子概述…

立体库堆垛机控制程序手动功能实现

手动操作功能模块 手动前后保护锁 *************提升手动程序段 手动上升&#xff0c;下降保护锁 **********货叉手动程序段

【第2章 Node.js基础】2.4 Node.js 全局对象(二) process 对象

process对象是一个全局对象&#xff0c;提供当前Node.js 进程信息并对其进行控制。通常用于编写本地命令行程序。 1.进程事件 process对象是EventEmitter类的实例&#xff0c;因此可以使用事件的方式来处理和监听process对象的各种事件。以下是一些常用的process对象事件&…

Webpack 性能优化 二次编译速度提升3倍!

本文作者为 360 奇舞团前端开发工程师 Rien. 本篇文章主要记录 webpack 的一次性能优化。 现状 随着业务复杂度的不断增加&#xff0c;项目也开始变得庞大&#xff0c;工程模块的体积也不断增加&#xff0c;webpack 编译的时间也会越来越久&#xff0c;我们现在的项目二次编译的…

医院安全(不良)事件管理系统源码 不良事件报告全套源码

不良事件管理系统是一种专为企业或组织设计的软件工具&#xff0c;用于跟踪、记录和管理不良事件。该系统可以有效地整合不良事件的收集、分类、分析和报告&#xff0c;帮助企业及时识别和处理不良事件&#xff0c;从而降低风险和损失。通过实时监控和自动化报告&#xff0c;该…

JavaScript数据类型和存储区别

目录 一、原始数据类型 二、引用数据类型 三、存储区别 四、常见错误 JavaScript是一种动态类型语言&#xff0c;这意味着变量可以在程序执行过程中改变其数据类型。了解JavaScript中的数据类型和它们的存储方式对于编写高效和可维护的代码至关重要。 在JavaScript中&…

世界互联网大会|云轴科技ZStack受邀分享云原生超融合

11月8日至10日“世界互联网大会乌镇峰会”在浙江嘉兴的乌镇开幕&#xff0c;大会的主题为“建设包容、普惠、有韧性的数字世界——携手构建网络空间命运共同体”&#xff0c;全球各界代表就热点焦点问题展开讨论&#xff0c;反映产业各界对互联网发展的前瞻思考&#xff0c;引领…

knife4j集成Swagger

knife4j集成 配置knife4j 第一步: 导入knife4j对应的maven坐标,knife4j是为MVC框架集成Swagger生成API文档的增强解决方案 <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><ver…

中国平安:短期面临两项重大风险,长期具有增长潜力

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 中国平安面临的短期风险 在过去的一个月里&#xff0c;中国平安(02318)(601318)的股价已经下跌了16.4%&#xff0c;而同期标普500指数则上涨了1.3%。所以&#xff0c;猛兽财经认为&#xff0c;中国平安近期的股价疲软&…

python数据结构与算法-02_数组和列表

线性结构 本节我们从最简单和常用的线性结构开始&#xff0c;并结合 Python 语言本身内置的数据结构和其底层实现方式来讲解。 虽然本质上数据结构的思想是语言无关的&#xff0c;但是了解 Python 的实现方式有助于你避免一些坑。 我们会在代码中注释出操作的时间复杂度。 数…

nginx之使用与配置教程

目录 简介 优点 安装 目录结构 nginx.conf配置文件结构 server虚拟主机配置 listen server_name location root index try_files proxy_pass 使用 反向代理 配置语法 常用指令 proxy_pass proxy_set_header proxy_redirect 负载均衡 负载均衡策略 轮询&…

发现一款好用的制作企业杂志网站/强推

除了展示企业的信息&#xff0c;企业杂志还可以成为员工展示自我、表达情感的电子书。你可以鼓励员工分享他们的故事、他们的想法、他们的创新。这样&#xff0c;企业杂志就成为了一个充满活力和创新的空间。 那么如何制作一本企业杂志呢&#xff1f;给大家推荐一款实用的网站&…

Hadoop3.3.4分布式安装

安装前提&#xff1a;已经配置好java环境&#xff0c;所有机器之间ssh的免密登录。 注意&#xff1a;下文中的flinkv1、flinkv2、flinkv3是三台服务器的别名 1.集群部署规划 注意&#xff1a;NameNode和SecondaryNameNode不要安装在同一台服务器 注意&#xff1a;ResourceMan…