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]这个值的长度)这个值更大,所以说我们得取一个最大的值。

  • 因此,递推公式为:

        vector<int> dp(nums.size(),1);
int ans=1;
for(int i=1;i<nums.size();i++){
for(int j=0;j<i;j++){
if(nums[i]>nums[j]) dp[i]=max(dp[i],dp[j]+1);
}
ans=max(ans,dp[i]);
}

遍历顺序

  • 由于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数组是正确的

代码实现

class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
vector<int> dp(nums.size(),1);
//这个初始值为1,因为至少都有长度为1的递增子序列
int ans=1;
for(int i=1;i<nums.size();i++){
for(int j=0;j<i;j++){
if(nums[i]>nums[j]) dp[i]=max(dp[i],dp[j]+1);
}
ans=max(ans,dp[i]);
}
return ans;
}
};

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. .NET项目中使用HtmlSanitizer防止XSS攻击

    .NET项目中使用HtmlSanitizer防止XSS攻击 前言 最近博客也是上线了留言板功能,但是没有做审核(太懒了),然后在留言的时候可以输入<script>alert('xss')& ...

  2. 修改Git Commit提交记录的用户名Name和邮箱Email

    修改Git 本次Commit提交记录的用户名Name和邮箱Email git commit --amend --author="new-name <xxx@new.com>&qu ...

  3. 高通驱动树中的GPIO详解

    高通驱动树中的GPIO详解 reference:https://blog.csdn.net/baidu_37503452/article/details/80257441 Drive Strength ...

  4. AT24C02、04、08、16 操作说明

    我们这里介绍一下常见的EEPROM,ATMEL的AT24x系列中的AT24C02,学会了这个芯片,其他系列的芯片也是类似的. AT24C02的存储容量为2K bit,内容分成32页,每页8Byte ( ...

  5. uboot 添加 自定义命令

    --- title: uboot-uboot 添加 自定义命令 date: 2020-05-13 16:51:38 categories: tags: - uboot - cmd - config - ...

  6. Nginx常用操作

    Nginx Nginx的最重要的几个使用场景 静态资源服务,通过本地文件提供服务 反向代理服务,延伸出包括缓存,负载均衡等 API服务,OpenResty 相关概念 简单请求和非简单请求 请求方法是H ...

  7. CPU的保护模式

    保护模式是为了克服实模式低劣的内存管理方式,物理内存地址不能直接被程序访问,程序内部的地址需要被转化为物理地址后再去访问.实模式CPU运行环境16位,保护模式32位. 寄存器扩展: 由于CPU发展到3 ...

  8. [oeasy]python0116_文字的起源_苏美尔文明_楔形文字_两河流域

    文字起源 回忆上次内容 上次回顾了西里尔字符的编码过程 KOI-7 KOI-8   ISO-8859 系列进行总结 字符扩展 ascii 共 16 种 由iso组织制定 从 iso-8859-1 到 ...

  9. 封装的grid控件

    class CGridCtrl : public CWnd { DECLARE_DYNAMIC(CGridCtrl) public: void Create(CWnd* pParent, DWORD ...

  10. .NET TCP、UDP、Socket、WebSocket

    做.NET应用开发肯定会用到网络通信,而进程间通信是客户端开发使用频率较高的场景. 进程间通信方式主要有命名管道.消息队列.共享内存.Socket通信,个人使用最多的是Sokcet相关. 而Socke ...