Day52|动态规划part13:300.最长递增子序列、674. 最长连续递增序列

news2025/1/16 5:13:41

300. 最长递增子序列

leetcode链接:力扣题目链接

视频链接:动态规划之子序列问题,元素不连续!| LeetCode:300.最长递增子序列

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。
例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

示例 1:

输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
示例 2:

输入:nums = [0,1,0,3,2,3]
输出:4
示例 3:

输入:nums = [7,7,7,7,7,7,7]
输出:1

首先我们明确一下子序列的定义,子序列与子串(必须要连续)不同,子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。

动规五部曲

  1. 确定dp数组含义及下标

dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度。

这里明确dp[i]的含义很重要,因为这道题我们返回的结果不一定是dp[n - 1],而是dp中最大的一个,因为最长的序列不一定以nums[i]结尾。

  1. 确定dp数组的递推公式

考虑下面的情景,假设我们已经知道了 dp[0..4] 的所有结果,我们如何通过这些已知结果推出 dp[5]

image

想法就是如果前面的数比nums[i]小,那就是递增的,可以加入候选,我们取前面最大的加1,接到nums[i]上去,就是最长的子序列。使用两层for循环。

  1. dp数组的初始化

每个dp[i]即子序列长度最小都是1。

  1. 确定遍历顺序

没什么好说的,从前往后。

  1. 打印dp数组

最终代码;

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> dp(nums.size(), 1);
        int res = 0;
        for(int i = 0; i < nums.size(); i++){
            for(int j = 0; j < i; j++){
                if(nums[i] > nums[j]){
                    dp[i] = max(dp[j] + 1,dp[i]);
                }
            }
            res = dp[i] > res ? dp[i] : res;
        }
        //这里注意不是return dp[n - 1]了,牢记dp的含义;
        //return dp[nums.size() - 1];
        //return *max_element(dp.begin(),dp.end());
        return res;
    }
};

674. 最长连续递增序列(这题反而是easy难度)

leetcode链接:力扣题目链接

视频链接:动态规划之子序列问题,重点在于连续!| LeetCode:674.最长连续递增序列

给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。

连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。

示例 1:

输入:nums = [1,3,5,4,7]
输出:3
解释:最长连续递增序列是 [1,3,5], 长度为3。
尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 57 在原数组里被 4 隔开。 
示例 2:

输入:nums = [2,2,2,2,2]
输出:1
解释:最长连续递增序列是 [2], 长度为1

首先是贪心解法,只要nums[i+1]比nums[i]就记录,然后取最大的:

class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        int len = 1, maxLen = 1;
        for(int i = 0; i < nums.size() - 1; i++){
            if(nums[i + 1] > nums[i] ){
                len++;
            }else{
                maxLen = len > maxLen ? len : maxLen;
                cout<< maxLen<< ' ';
                len = 1;
            }
        }
        maxLen = len > maxLen ? len : maxLen;
        return maxLen;
    }
};

动规五部曲

  1. 确定dp数组下标及其含义

dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度。

返回的也是dp[i]中最大的那个。

  1. 确定递推公式

如果nums[i] > nums[i - 1],可以接上,即dp [i] = nums[i - 1] + 1。

如果不成立,中断,dp[i] = 1;

  1. dp数组的初始化

每个都初始化为1;

  1. 遍历顺序

显然是从左往右遍历。

  1. 打印dp数组

最终代码:

class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        if (nums.size() == 0) return 0;
        int result = 1;
        vector<int> dp(nums.size() ,1);
        for (int i = 1; i < nums.size(); i++) {
            if (nums[i] > nums[i - 1]) { // 连续记录
                dp[i] = dp[i - 1] + 1;
            }
            if (dp[i] > result) result = dp[i];
        }
        return result;
    }
};

718. 最长重复子数组

leetcode链接:力扣题目链接

视频链接:动态规划之子序列问题,想清楚DP数组的定义 | LeetCode:718.最长重复子数组

给两个整数数组 nums1 和 nums2 ,返回 两个数组中 公共的 、长度最长的子数组的长度 。

示例 1:

输入:nums1 = [1,2,3,2,1], nums2 = [3,2,1,4,7]
输出:3
解释:长度最长的公共子数组是 [3,2,1] 。
示例 2:

输入:nums1 = [0,0,0,0,0], nums2 = [0,0,0,0,0]
输出:5

这里要明确一下子数组的含义,注意题目中说的子数组,其实就是连续子序列。

如果用暴力,就是把所有的子序列都穷举出来,进行比较,这里复杂度太高肯定没办法AC。考虑动态规划算法。

动规五部曲

  1. 确定dp数组下标及其含义

dp[i][j] :以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最长重复子数组长度为dp[i][j]。 (特别注意: “以下标i - 1为结尾的A” 标明一定是 以A[i-1]为结尾的字符串 )

故此时dp[0][0]无意义,遍历都从dp[1][1]开始。

最后返回的是dp[i][j]中的最大值。

  1. 确定递推公式

如果A[i - 1]和B[j - 1]相等,那么dp[i][j] = dp[i -1][j - 1](接上了),

  1. dp数组的初始化

根据dp[i][j]的定义,dp[i][0] 和dp[0][j]其实都是没有意义的!

但dp[i][0] 和dp[0][j]要初始值,因为 为了方便递归公式dp[i][j] = dp[i - 1][j - 1] + 1;

所以dp[i][0] 和dp[0][j]初始化为0。

  1. 遍历顺序

外层for循环遍历A,内层for循环遍历B。同时在遍历时把dp[i][j]的最大值记录下来。

  1. 打印dp数组

image

最终代码:

class Solution {
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
        vector<vector<int>> dp(nums1.size() + 1, vector<int>(nums2.size() + 1,0));
        int res = 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;
                }
                if (dp[i][j] > res) {
                    res = dp[i][j];
                }
            }
        }
        return res;
    }
};
  • 时间复杂度:O(n × m),n 为A长度,m为B长度
  • 空间复杂度:O(n × m)

总结

  • 注意返回值不一定都是dp数组的最后一个,要留意dp数组含义和题意看看留dp中的哪个
  • 可以在最后进行处理,也可以在运行过程中处理,建议在dp定下来的时候就处理。

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

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

相关文章

Docker资源控制cgroups

文章目录 一、docker资源控制1、资源控制工具2、Cgroups四大功能 二、CPU 资源控制1、设置CPU使用率上限2、CPU压力测试3、Cgroups限制cpu使用率4、设置CPU资源占用比&#xff08;设置多个容器时才有效&#xff09;5、设置容器绑定指定的CPU 三、对内存使用的限制四、对磁盘IO配…

【C++】—— c++11之智能指针

前言&#xff1a; 本期&#xff0c;我们将要学习的是在c11中新提出的概念——异常指针&#xff01; 目录 &#xff08;一&#xff09;智能指针的引入 &#xff08;二&#xff09;内存泄漏 1、什么是内存泄漏&#xff0c;内存泄漏的危害 2、内存泄漏分类&#xff08;了解&a…

访问0xdddddddd内存地址引发软件崩溃的问题排查

目录 1、问题描述 2、访问空指针或者野指针 3、常见的异常值 4、0xdddddddd内存访问违例问题分析与排查 5、关于0xcdcdcdcd和0xfeeefeee异常值的排查案例 6、最后 VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&#xff09;ht…

循环购模式:美妆行业的新趋势

美妆是一种能够提升自信和魅力的艺术&#xff0c;它让每个人都可以展现自己的个性和风格。但是&#xff0c;美妆也是一种需要不断更新和学习的技能&#xff0c;它需要消费者投入时间和金钱&#xff0c;才能找到适合自己的产品和方法。有没有一种方式&#xff0c;可以让美妆变得…

用python画一个柱状图可能用到的代码【完整版】

画柱状图 导入包 import torch as t import numpy as np import pandas as pd import matplotlib.pyplot as plt import joblib import matplotlib as mpl设置默认字体格式为"Times New Roman" font_name Times New Roman mpl.rcParams[font.family] font_name通…

stable diffusion实践操作-提示词插件安装与使用

本文专门开一节写提示词相关的内容&#xff0c;在看之前&#xff0c;可以同步关注&#xff1a; stable diffusion实践操作 正文 1、提示词插件安装 1.1、 安装 1.2 加载【应用更改并重载前端】 1.3 界面展示 1.3.-4 使用 里面有个收藏列表&#xff0c;可以收藏以前的所有提示…

STM32f103入门(7)pwm驱动led驱动舵机驱动直流电机

PWM驱动 PWM介绍TIM_OC1Init 配置通道TIM_OCStructInit 输出比较参数默认值输出比较模式 TIM_OCInitstructure输出比较极性 TIM_OCInitstructure设置输出使能以下三个决定了PWM的频率 占空比初始化通道 TIM_OC1Init(TIM2, &TIM_OCInitstructure);GPIO复用 PWM通道 驱动LED复…

2022年09月 C/C++(五级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;城堡问题 1 2 3 4 5 6 7 ############################# 1 # | # | # | | # #####—#####—#—#####—# 2 # # | # # # # # #—#####—#####—#####—# 3 # | | # # # # # #—#########—#####—#—# 4 # # | | | | # # ############################# (图 1)…

关于git约定式提交IDEA

背景 因为git提交的消息不规范导致被乱喷&#xff0c;所以领导统一规定了约定式提交 官话 约定式提交官网地址 约定式提交规范是一种基于提交信息的轻量级约定。 它提供了一组简单规则来创建清晰的提交历史&#xff1b; 这更有利于编写自动化工具。 通过在提交信息中描述功能…

【算法】递归的概念、基本思想

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

LuatOS 开发指南

NDK 开发 官方教程 官方例程 API 下载软件 下载官方NDK例程压缩包到本地&#xff0c;并解压。可以看到目录如下&#xff1a; doc: 文档教程 env: 编译环境 example: NDK示例 platform: 需要编译的平台&#xff08;air72x/air8xx&#xff09; tools: 其他辅助软件 VSCode 使…

问道管理:成交量买卖公式?

跟着股票商场的如火如荼&#xff0c;人们对于怎么解读和使用成交量进行股票生意的需求日积月累。成交量是指在某一特定时间内进行的股票生意的数量&#xff0c;它是投资者们研判商场状况和制定生意战略的重要指标之一。那么&#xff0c;是否存在一种最厉害的成交量生意公式呢&a…

day31 集合

一、Collection 创建对象 Collection c3 new HashSet(); //元素不可重复 无序 Collection c1 new ArrayList(); //元素可重复 有序collection方法 c.add() 添加引用类型数据 c.addAll() 添加collection对象 c.isEmpty() 判断是否为空 c.clear() 清空所有类容 c.…

深入了解Docker镜像操作

Docker是一种流行的容器化平台&#xff0c;它允许开发者将应用程序及其依赖项打包成容器&#xff0c;以便在不同环境中轻松部署和运行。在Docker中&#xff0c;镜像是构建容器的基础&#xff0c;有些家人们可能在服务器上对docker镜像的操作命令不是很熟悉&#xff0c;本文将深…

xx音乐app逆向分析

目标 看一下评论的请求 抓包 这里使用httpcanary 请求包如下 POST /index.php?rcommentsv2/getCommentWithLike&codeca53b96fe5a1d9c22d71c8f522ef7c4f&childrenidcollection_3_1069003079_330_0&kugouid1959585341&ver10&clienttoken7123ecc548ec46d…

frida动态调试入门02——hook加密函数

说明 frida是一款Python工具可以方便对内存进行hook修改代码逻辑在移动端安全和逆向过程中常用到。 前置知识 frida动态调试入门01——定位关键代码 https://blog.csdn.net/qq_41690468/article/details/132607065 定位函数 关键函数 String code RequestUtil.paraMap(ad…

Linux 指令心法(四)`touch` 创建一个新的空文件

文章目录 命令的概述和用途命令的用法命令行选项和参数的详细说明命令的示例命令的注意事项或提示 命令的概述和用途 touch 是一个用于在 Linux 和 Unix 系统中创建空文件或更改现有文件的访问和修改时间的命令。如果指定的文件不存在&#xff0c;touch会创建一个新的空文件&a…

九、idSpanMap使用基数树代替原本的unordered_map 十、使用基数树前后性能对比

九、idSpanMap使用基数树代替原本的unordered_map 我们原本的idSpanMap用的是STL容器中的unordered_map哈希桶&#xff0c;因为STL的容器本身是不保证线程安全的&#xff0c;所以我们在访问时需要加锁保证线程安全&#xff0c;这也就是我们写的内存池的性能的瓶颈点。因为我做…

【MySQL】基础知识(二)

MySQL基础知识(二) 文章目录 MySQL基础知识(二)01 表操作1.1 创建表1.2 查看所有表1.3 查看指定表的结构1.4 删除表练习 02 CURD2.1 新增2.1.1 指定列插入2.1.2 datetime类型插入 2.2 查询2.2.1 全列查询2.2.2 指定列查询2.2.3 查询字段为表达式2.2.4 别名查询2.2.5 去重2.2.6 …

【Cookie和Session的那些事儿】

&#x1f320;作者&#xff1a;TheMythWS. &#x1f386;专栏&#xff1a;《集合与数据结构》 &#x1f387;座右铭&#xff1a;不走心的努力都是在敷衍自己&#xff0c;让自己所做的选择&#xff0c;熠熠发光。 目录 认识Cookie和Session Cookie Cookie对象的特点 Cookie对…