LeetCode300.最长递增子序列

力扣题目链接(opens new window)

给你一个整数数组 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 <= nums.length <= 2500
  • -104 <= nums[i] <= 104

动态规划思路讲解

状态变量以及其含义

  • 我们设置状态变量dp[i],表示以nums[i]为结尾的最长上升子序列的长度
  • 我们举个例子,以示例1为例,我们来推导一下为什么可以用dp[i]来表示以nums[i]为结尾的最长上升子序列
  • nums数组: [10,9,2,5,3,7,101,18]
  1. 以10结尾的最长上升子序为:[10]
  2. 以9为结尾的最长上升子序列为:[9]
  3. 以2为结尾的最长上升子序列为:[2]
  4. 以5为结尾的最长上升子序列为:[2,5]
  5. 以3为结尾的最长上升子序列为:[2,3]
  6. 以7为结尾的最长上升子序列为:[2,3,7]
  7. 以101为结尾的最长上升子序列为:[2,3,7,101]
  8. 以18为结尾的最长上升子序列为:[2,3,7,18]
  • 由上面的分析可知,以101为结尾的最长上升子序列是我们要求的最终的结果,并且这个结果的状态可以由前面的状态推出,因此我们设立dp[i]这个状态变量表示以nums[i]为结尾的最长上升子序列。

递推公式:

  • 我们可以设立两个指针i,j来进行操作,i指针来遍历nums的每一个元素,j指针来遍历nums[i]之前的所有元素,由于我们要找出最大的上升子序列,所以说每个元素我们都要找到nums中在这个元素之前的所有比这个元素要小的元素,这样才能尽可能的构成最大的递增子序列。

  • 所以说我们使用i,j指针来遍历字符串。

  • nums[i]>nums[j]时,意味着我们当前元素大于之前的一个元素,这两个元素之间可以构成一个递增子序列,所以说我们可能要进行更新dp[i],为什么是可能呢?因为我们dp[i]的值可能比dp[j]+1(dp[j]+1的意思就是前j个元素构成的递增序列,再加上num[i]这个值的长度)这个值更大,所以说我们得取一个最大的值。

  • 因此,递推公式为:

  1. vector<int> dp(nums.size(),1);
  2. int ans=1;
  3. for(int i=1;i<nums.size();i++){
  4. for(int j=0;j<i;j++){
  5. if(nums[i]>nums[j]) dp[i]=max(dp[i],dp[j]+1);
  6. }
  7. ans=max(ans,dp[i]);
  8. }

遍历顺序

  • 由于dp[i]是要由它之前的元素dp[j]来推导的,因此遍历顺序明显是从前向后遍历

如何初始化?

  • 首先,我们将dp[i]中的所有值全都初始化为1,因为每个元素至少都有一个递增子序列(也就是它本身构成的子序列)
  • 然后,依据我们的递推公式从前向后进行初始化操作即可。

举例验证dp数组

  • nums数组: [10,9,2,5,3,7,101,18]
  1. 以10结尾的最长上升子序为:[10]
  2. 以9为结尾的最长上升子序列为:[9]
  3. 以2为结尾的最长上升子序列为:[2]
  4. 以5为结尾的最长上升子序列为:[2,5]
  5. 以3为结尾的最长上升子序列为:[2,3]
  6. 以7为结尾的最长上升子序列为:[2,3,7]
  7. 以101为结尾的最长上升子序列为:[2,3,7,101]
  8. 以18为结尾的最长上升子序列为:[2,3,7,18]
  • 这个例子也说明了我们的dp数组是正确的

代码实现

  1. class Solution {
  2. public:
  3. int lengthOfLIS(vector<int>& nums) {
  4. vector<int> dp(nums.size(),1);
  5. //这个初始值为1,因为至少都有长度为1的递增子序列
  6. int ans=1;
  7. for(int i=1;i<nums.size();i++){
  8. for(int j=0;j<i;j++){
  9. if(nums[i]>nums[j]) dp[i]=max(dp[i],dp[j]+1);
  10. }
  11. ans=max(ans,dp[i]);
  12. }
  13. return ans;
  14. }
  15. };

LeetCode300.最长递增子序列的更多相关文章

  1. LeetCode--300. 最长递增子序列

    题目:给定一个无序的整数数组,找到其中最长上升子序列的长度. 示例: 输入: [10,9,2,5,3,7,101,18] 输出: 4 解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4 ...

  2. leetcode300. Longest Increasing Subsequence 最长递增子序列 、674. Longest Continuous Increasing Subsequence

    Longest Increasing Subsequence 最长递增子序列 子序列不是数组中连续的数. dp表达的意思是以i结尾的最长子序列,而不是前i个数字的最长子序列. 初始化是dp所有的都为1 ...

  3. (转载)最长递增子序列 O(NlogN)算法

    原博文:传送门 最长递增子序列(Longest Increasing Subsequence) 下面我们简记为 LIS. 定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则 ...

  4. 最长公共子序列(LCS)和最长递增子序列(LIS)的求解

    一.最长公共子序列 经典的动态规划问题,大概的陈述如下: 给定两个序列a1,a2,a3,a4,a5,a6......和b1,b2,b3,b4,b5,b6.......,要求这样的序列使得c同时是这两个 ...

  5. 最长递增子序列 O(NlogN)算法

    转自:点击打开链接 最长递增子序列,Longest Increasing Subsequence 下面我们简记为 LIS. 排序+LCS算法 以及 DP算法就忽略了,这两个太容易理解了. 假设存在一个 ...

  6. 51nod 1134 最长递增子序列

    题目链接:51nod 1134 最长递增子序列 #include<cstdio> #include<cstring> #include<algorithm> usi ...

  7. 动态规划 - 最长递增子序列(LIS)

    最长递增子序列是动态规划中经典的问题,详细如下: 在一个已知的序列{a1,a2,...,an}中,取出若干数组组成新的序列{ai1,ai2,...,aim},其中下标i1,i2,...,im保持递增, ...

  8. 最长递增子序列问题 nyoj 17单调递增最长子序列 nyoj 79拦截导弹

    一,    最长递增子序列问题的描述 设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1< ...

  9. 2.16 最长递增子序列 LIS

    [本文链接] http://www.cnblogs.com/hellogiser/p/dp-of-LIS.html [分析] 思路一:设序列为A,对序列进行排序后得到B,那么A的最长递增子序列LIS就 ...

  10. 【动态规划】拦截导弹_dilworth定理_最长递增子序列

    问题 K: [动态规划]拦截导弹 时间限制: 1 Sec  内存限制: 256 MB提交: 39  解决: 10[提交][状态][讨论版] 题目描述 张琪曼:“老师,修罗场是什么?” 墨老师:“修罗是 ...

随机推荐

  1. python重拾第九天-进程、线程、协程

    本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者 ...

  2. 化合物同位素理论同位素分布计算软件Isopro 3.0

    大家好,今天分享一款软件,即可以计算化合物理论同位素分布的软件Isopro 3.0.在做质谱的实验时,特别对合成的化合物进行质量表征时,往往要求ppm绝对值在5以内,对质谱的分辨率要求很高.对于小分子 ...

  3. 【韦东山】嵌入式全系统:单片机-linux-Android对硬件操作的不同侧重点

    我是韦东山,一直从事嵌入式Linux培训,最近打算连载一系列文章. 正在录制全新的嵌入式Linux视频,使用新路线,不再从裸机/uboot开始,效率更高. 对应文档也会写成书<<嵌入式Li ...

  4. OpenWrt中的LuCi和Lua一些总结

    Lua.LuCi Lua是一种小巧的脚本语言,和Python一样,Lua脚本的运行需要Lua解释器: UCI(Unified Configuration Interface)是OpenWrt实现所有系 ...

  5. 如何用python计算不定积分

    在Python中,计算不定积分(即原函数或反导数)可以通过SymPy库实现.SymPy是一个用于符号数学的Python库,支持许多类型的数学对象,包括整数.有理数.实数.复数.函数.极限.积分.微分. ...

  6. 记一次 .NET某酒业业务系统 崩溃分析

    一:背景 1. 讲故事 前些天有位朋友找到我,说他的程序每次关闭时就会自动崩溃,一直找不到原因让我帮忙看一下怎么回事,这位朋友应该是第二次找我了,分析了下 dump 还是挺经典的,拿出来给大家分享一下 ...

  7. 深度学习pytorch常用操作以及流程

    在微信公众号上看到这篇文章,担心以后想找的时候迷路,所以记录到了自己的博客上,侵扰致歉,随时联系可删除. 1.基本张量操作 1. 1 创建张量 介绍: torch.tensor() 是 PyTorch ...

  8. css浅谈Flex布局

    1.打开Flex布局 .box{ display: flex; } 2.容器的属性 flex-direction flex-wrap flex-flow justify-content align-i ...

  9. 轻松掌握useAsyncData获取异步数据

    title: 轻松掌握useAsyncData获取异步数据 date: 2024/7/12 updated: 2024/7/12 author: cmdragon excerpt: 摘要:本文详细介绍 ...

  10. .NET Core 3.x 基于Autofac的AOP缓存

    一.依赖包 二.定义一个简单的缓存接口 /// <summary> /// 简单的缓存接口,只有查询和添加,以后会进行扩展 /// </summary> public inte ...