【动态规划-4.2 最长递增子序列(LIS)】力扣300. 最长递增子序列

news2024/10/10 6:16:06

给你一个整数数组 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

在这里插入图片描述

动态规划

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        if(n == 0){
            return 0;
        }

        vector<int> dp(n, 1);
        for(int i = 0; i < n; i++){
            for(int j = 0; j < i; j++){
                if(nums[i] > nums[j]){
                    dp[i] = max(dp[i], dp[j] + 1);
                }
            }
        }
        return *max_element(dp.begin(), dp.end());
    }
};

时间复杂度:O(n^2),其中 n 为数组 nums 的长度。动态规划的状态数为 n,计算状态 dp[i] 时,需要 O(n) 的时间遍历 dp[0…i−1] 的所有状态。

空间复杂度:O(n),需要额外使用长度为 n 的 dp 数组。

vector dp(n, 1); 创建了一个长度为 n 的 dp 数组,初始值全部设为 1。dp[i] 表示以 nums[i] 结尾的最长递增子序列的长度。
为什么初始值为 1?因为每个元素本身都可以成为一个递增子序列。

if(nums[i] > nums[j]),如果 nums[i] 大于 nums[j],则意味着可以将 nums[i] 接在 nums[j] 之后形成一个更长的递增子序列。
dp[i] = max(dp[i], dp[j] + 1),更新 dp[i],选择 dp[i] 和 dp[j] + 1 中的较大值,表示以 nums[i] 结尾的最长递增子序列的长度。

return *max_element(dp.begin(), dp.end()); 返回 dp 数组中的最大值,即整个数组中最长递增子序列的长度。

贪心+二分查找

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int len = 1;
        int n = nums.size();
        if (n == 0) {
            return 0;
        }
        //d[i]代表长度为i的最长上升子序列的末尾元素最小值
        vector<int> d(n+1);
        d[1] = nums[0];
        for(int i = 1; i < n; i++){
            if(nums[i] > d[len]){
                d[++len] = nums[i];
            }
            else{
                int l = 1, r = len, pos = 0;
                while(r >= l){
                    int mid = (l+r) >> 1;
                    if(d[mid] < nums[i]){
                        l = mid + 1;
                        pos = mid;
                    }
                    else{
                        r = mid - 1;
                    }
                }
                d[pos+1] = nums[i];
            }  
        }
        return len;
    }
};

时间复杂度:O(nlogn)。数组 nums 的长度为 n,我们依次用数组中的元素去更新 d 数组,而更新 d 数组时需要进行 O(logn) 的二分搜索,所以总时间复杂度为 O(nlogn)。

空间复杂度:O(n),需要额外使用长度为 n 的 d 数组。

vector<int> d(n+1);d 数组用于记录长度为 i 的最长上升子序列的最小结尾元素(即 d[i] 代表长度为 i 的子序列的末尾元素的最小值)。这里将其初始化为大小为 n+1。

这个解法的巧妙之处在于,他在遍历nums[i]的时候,就已经在尝试拼凑最长递增的子序列。要满足最长递增子序列,我们要求在相同长度的子序列下,让末尾元素尽量地小。

所以我们在尝试拼凑子序列的时候,我们会将nums[i]与目前的最长子序列的最后一个元素进行比较,如果nums[i]较大,那么就说明nums[i]可以接在这个子序列中拼凑出一个更长的子序列。

如果nums[I]较小,我们就要使用二分查找来找到d数组中小于nums[i]的最大元素,也就是说是比d数组中比nums[i]小且最接近nums[i]的数。由于nums[i]经过二分查找,肯定比d[pos+1]要小,所以在相同长度的子序列中,末尾最小元素就为nums[i]。

思考
我们需要的是len的长度,len++的来源于nums[i]大于d[len],如果d[len]被替换成更小的nums[i],会对后续的len++有正面影响,如果nums[i]替换掉的不是d[len],假设是d[len-1],那么会减小d[len-1]的值,在后续的nums[i]的替换中,会变得更容易被选为pos,从而替换d[len-1],然后对后续的len++有正面影响。

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

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

相关文章

LVM——让Linux磁盘空间的弹性管理

什么是LVM&#xff1f; LVM(Logical Volume Manager)逻辑卷管理是在Linux2.4内核以上实现的磁盘管理技术。它是Linux环境下对 磁盘分区进行管理的一种机制。现在不仅仅是Linux系统上可以使用LVM这种磁盘管理机制&#xff0c;对于其它的类UNIX操作系统&#xff0c;以及windows操…

用Manim简单解释奇异值分解(SVD)和图像处理方面的应

一&#xff0c;介绍 奇异值分解&#xff08;SVD&#xff09;是一种重要的矩阵分解技术&#xff0c;在统计学、信号处理和机器学习等领域有广泛应用。对于任意给定的矩阵 A&#xff08;可以是任意形状的矩阵&#xff09;&#xff0c;SVD将其分解为三个特定的矩阵的乘积&#x…

【时间盒子】-【9.任务设置项】自定义任务名称、任务时长等设置项组件

Tips: Stage、Link装饰器的使用&#xff1b; 参考我的帖子&#xff1a;https://developer.huawei.com/consumer/cn/forum/topic/0208152234389094513?fid0101587866109860105 一、预览 红色框&#xff1a;任务设置项列表&#xff0c;把它定义为一个组件对象SettingList。绿…

Python 工具库每日推荐【PyPDF2】

文章目录 引言Python PDF 处理库的重要性今日推荐:PyPDF2 工具库主要功能:使用场景:安装与配置快速上手示例代码代码解释实际应用案例案例:PDF文件合并案例分析高级特性加密和解密PDF添加水印扩展阅读与资源优缺点分析优点:缺点:总结【 已更新完 TypeScript 设计模式 专栏…

Vue基础(2)检测数据原理~生命周期

文章目录 检测数据原理1.更新时遇到的问题2.检测数据的原理-对象3. vue.set()的使用 收集表单数据过滤器内置指令1.v-text2.v-html3.v-cloak4.v-once5.v-pre 自定义指令生命周期1.挂载流程2.更新流程3.销毁流程 检测数据原理 1.Vue会监视data中的所有层次的数据 2.如何监测对象…

10月8日星期二今日早报简报微语报早读

10月8日星期二&#xff0c;农历九月初六&#xff0c;早报#微语早读。 1、我国自主研制的300兆瓦级F级重型燃气轮机在上海首次点火成功&#xff1b; 2、2024国庆档超21亿收官&#xff1a;《志愿军&#xff1a;存亡之战》票房8亿夺冠&#xff1b; 3、维克托安布罗斯&#xff0…

STM32工程环境搭建(库函数开发)

目录 1、移植固件库&标准库 2、新建工程 以STM32f401作为例子进行环境搭建 1、移植固件库&标准库 ①桌面创建工程文件夹并且提取内核文件 用户文件&#xff1a;用户自己编写的程序文件 .c .h文件 .c文件&#xff1a;具体函数功能源代码 .h文件&#xff1a;宏定义…

ctf.bugku - bp (弱密码top1000)

题目来源&#xff1a; bp - Bugku CTF 首先&#xff0c;下载top1000 &#xff0c;弱密码文本&#xff1a; PasswordDic/top1000.txt at master k8gege/PasswordDic GitHub 访问页面&#xff0c;随便输入个密码 发送请求到 intruder 以密码问参数 加载top1000.txt 密码文本&…

springboot开发网站-使用redis数据库定时特征限制指定ip的访问次数

springboot开发网站-使用redis数据库定时特征限制指定ip的访问次数。近期网站经常有人恶意访问&#xff0c;提交了很多垃圾信息。为了屏蔽这类灌水帖&#xff0c;打算屏蔽ip地址&#xff0c;限制24小时内只能访问1次某个接口。下面是测试的案例代码内容。 1&#xff1a;首先&am…

实验三 Web基础-JavaScript

实验三 Web基础-JavaScript 目的&#xff1a; 1、理解和掌握Javascript基本语法 2、掌握JavaScript操作表单对象的方法 3、理解和掌握JavaScript的函数与事件 4、理解JavaScript的内置对象 实验要求&#xff1a; 1、使用JavaScript语言实现实验要求 2、要求提交实验报告&…

HTB:Pennyworth[WriteUP]

目录 连接至HTB服务器并启动靶机 1.What does the acronym CVE stand for? 2.What do the three letters in CIA, referring to the CIA triad in cybersecurity, stand for? 3.What is the version of the service running on port 8080? 4.What version of Jenkins i…

【C++11】可变模板参数

文章目录 可变模板参数的概念递归函数方式展开参数包 STL容器中的empalce相关的接口函数emplace 与 insert / push_back 的区别 可变模板参数的概念 可变参数模板是 C11 引入的一种模板特性&#xff0c;允许定义可以接收任意数量参数的模板&#xff0c;广泛应用于函数和类的设计…

【js逆向学习】极志愿 javascript+python+rpc

JSRPC使用方式 逆向目标逆向过程逆向分析1、什么是 websocket2、websocket的原理3、总体过程3.1 环境说明3.2 python服务端代码3.3 python客户端代码 4、Sekiro-RPC4.1 执行方式4.2 客户端环境4.3 参数说明4.4 SK API4.5 python代码调试4.6 代码注入流程 逆向总结 逆向目标 网…

【STM32开发之寄存器版】(六)-通用定时器中断

一、前言 STM32定时器分类 STM32103ZET6具备8个定时器TIMx(x 1,2,...,8)。其中&#xff0c;TIM1和TIM8为高级定时器&#xff0c;TIM2-TIM6为通用定时器&#xff0c;TIM6和TIM7为基本定时器&#xff0c;本文将以TIM3通用定时器为例&#xff0c;分析STM32定时器工作的底层寄存器…

mysql读写分离的最佳实践

一. 传统的读写分离方式 在 MySQL 中实现读写分离可以通过以下几种方式来达到目的&#xff1a; 1. 主从复制 使用主从复制&#xff08;Master-Slave Replication&#xff09;是实现读写分离的常见方式。 主库&#xff1a;处理所有的写入操作&#xff08;INSERT、UPDATE、DE…

Qt+VS2019+大恒相机相机回调方式总结

一、前言 大恒驱动安装完成后&#xff0c;在安装目录有SDK调用文档&#xff0c;里面有更详细的调用介绍&#xff0c;此文档对近期做的Demo做一个回顾性总结。 二、调用流程概述 三、针对性内容介绍&#xff1a; 1. 在执行相机操作之前&#xff0c;需要先执行此代码&#xff1…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-07

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-07 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-07目录1. Evaluation of Large Language Models for Summarization Tasks in the Medical Domain: A Narrative Review摘要研究…

rust中async/await的使用

在Rust中&#xff0c;async/await 用于编写异步代码。它允许您以同步的方式编写异步代码&#xff0c;使得异步操作更易于理解和编写。 安装依赖&#xff1a; cargo add futures cargo add async-std 使用示例&#xff1a; 示例1&#xff1a; use async_std::task::block_o…

学习MDX

MDX&#xff08;Markdown JSX&#xff09;是一种开源的文件格式&#xff0c;它允许你在Markdown文件中使用JavaScript表达式和组件。MDX将Markdown的易用性与React组件的强大功能结合起来&#xff0c;使得你可以在编写文档、博客文章或其他内容时&#xff0c;嵌入可交互的组件…

顶会论文复现:PROVING TEST SET CONTAMINATION IN BLACK BOX LANGUAGE MODELS

文章目录 1 资料2 我的总结3 复现源码首先你需要有gpt的api接口安装&#xff1a;数据集执行指令源码 4 结果 1 资料 我复现的源码:https://github.com/Whiffe/test_set_contamination 官网源码&#xff1a;https://github.com/tatsu-lab/test_set_contamination 论文&#x…