题目描述:

给定一个无序的整数数组,找到其中最长上升子序列的长度。

示例:

输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
说明: 可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n2) 。
进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?

思路分析:(题解来自:https://leetcode-cn.com/u/liweiwei1419/

动态规划,时间复杂度为 O(N^2);

“动态规划”的两个步骤是思考“状态”以及“状态转移方程”。

有的资料又将“动态规划”分为 3 步:

base case:思考问题规模最小的时候,是什么情况;
update function:自下而上思考这个问题,即上面的“状态转移方程”;
gola:重点强调了输出是什么,很多时候输出并不一定是最后一个状态。
我觉得这种分法更细致一点,“状态”以及“状态转移方程”也没有问题,但是我觉得还要加上一个,思考一下“输出”是什么,即将第 2 种的第 3 步加上去,在下面的分析中,我还会强调这一点。

1、定义状态

首先我们考虑能否将题目的问法定义成状态,即 dp[i] 表示长度为 i 的最长上升子序列的长度,但仔细思考之后,我们发现:由于“子序列”不要求连续,长度为 i - 1 的最长上升子序列,与长度为 i 的“最长上升子序列之间的递推关系并不那么容易得到。

但我们由「力扣」第 3 题:“无重复字符的最长子串”以及「力扣」第 53 题:“最大子序和”这两个问题的经验,再结合题意,可以知道,“上升”的递推关系是:看子序列最后一个数,如果一个新数,比子序列最后一个数还大,那么就可以放在这个子序列的最后,形成一个更长的子序列。反正一个子序列一定会以一个数字结尾,那我就将状态成以 nums[i] 结尾的“最长上升子序列”的长度,这一点是常见的。

dp[i]:表示以第 i 个数字为结尾的“最长上升子序列”的长度。即在 [0, ..., i] 的范围内,选择 以数字 nums[i] 结尾 可以获得的最长上升子序列的长度。注意:以第 i 个数字为结尾,即 要求 nums[i] 必须被选取。

初始化的时候,因为每个元素自己可以认为是一个长度为 1 的子序列,所以可以将 dp 数组的值全部设置为 1。

定义输出:下面要考虑一下输出,由于状态不是题目中的问法,因此不能将最后一个状态作为输出,这里输出是把 dp[0]、dp[1]、……、dp[n - 1] 全部看一遍,取最大值。

2、推导“状态转移方程”

遍历到索引是 i 的数的时候,根据上面“状态”的定义,考虑把 i 之前的所有的数都看一遍,只要当前的数 nums[i] 严格大于之前的某个数,那么 nums[i] 就可以接在这个数后面形成一个更长的上升子序列。因此,dp[i] 就是之前严格小于 nums[i] 的“状态”最大值加 1。

因此,状态转移方程是:

dp[i] = max{1 + dp[j] for j < i if nums[j] < nums[i]}

代码实现:

class Solution {
public static int lengthOfLIS(int[] nums) { int len = nums.length;
int[] dp = new int[len];
Arrays.fill(dp, 1);
//初始化dp数组,每个元素至少都是以它自身为结尾,长度为1的自序列
int maxLen = 0;
//从第二个元素开始
for (int i = 1; i < len; i++) {
//以当前元素为结尾
int curVal = nums[i];
for (int j = 0; j < i; j++) {
//当前元素严格大于之前的任何一个片段,则当前元素都可以加在这个区间后面,形成+1长度的自序列
if (curVal > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}
for (int element : dp) {
maxLen = Math.max(maxLen, element);
}
return maxLen;
}
}

时间复杂度:O(n^2)

空间复杂度:O(n)

Leetcode题目300.最长上升子序列(动态规划-中等)的更多相关文章

  1. 【LeetCode】300.最长递增子序列——暴力递归(O(n^3)),动态规划(O(n^2)),动态规划+二分法(O(nlogn))

    算法新手,刷力扣遇到这题,搞了半天终于搞懂了,来这记录一下,欢迎大家交流指点. 题目描述: 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度. 子序列是由数组派生而来的序列,删除(或不删 ...

  2. [LeetCode] 300. 最长上升子序列 ☆☆☆(动态规划 二分)

    https://leetcode-cn.com/problems/longest-increasing-subsequence/solution/dong-tai-gui-hua-she-ji-fan ...

  3. Leetcode题目64.最小路径和(动态规划-中等)

    题目描述: 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 示例: 输入: [ [1,3,1], [1, ...

  4. Leetcode——300. 最长上升子序列

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

  5. Java实现 LeetCode 300 最长上升子序列

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

  6. 1. 线性DP 300. 最长上升子序列 (LIS)

    最经典单串: 300. 最长上升子序列 (LIS) https://leetcode-cn.com/problems/longest-increasing-subsequence/submission ...

  7. LeetCode 300. 最长上升子序列(Longest Increasing Subsequence)

    题目描述 给出一个无序的整形数组,找到最长上升子序列的长度. 例如, 给出 [10, 9, 2, 5, 3, 7, 101, 18], 最长的上升子序列是 [2, 3, 7, 101],因此它的长度是 ...

  8. LeetCode 300——最长上升子序列

    1. 题目 2. 解答 2.1. 动态规划 我们定义状态 state[i] 表示以 nums[i] 为结尾元素的最长上升子序列的长度,那么状态转移方程为: \[state[i] = max(state ...

  9. leetcode 300最长上升子序列

    用递归DFS遍历所有组合肯定积分会超时,原因是有很多重复的操作,可以想象每次回溯后肯定会有重复操作.所以改用动态规划.建立一个vector<int>memo,初始化为1,memo[i]表示 ...

随机推荐

  1. sudo命令 sudoers文件

    超级用户权限 # Host alias specification Host_Alias HA = 192.168.1.1, 192.168.1.2 # User alias specificatio ...

  2. dubbo常见异常及解决方式

    1.出现RpcException: Failed to invoke the method post in the service com.xxx.xxx.xxx异常怎么办?表示调用失败1.检查网络是 ...

  3. vue作用域插槽

    简而言之,作用域插槽就是让插槽内容能够访问子组件中的数据. 案例如下:有CurUser组件 <template> <span> <!-- 在slot 元素上绑定user, ...

  4. springboot 部署到tomcat中,项目总是重新部署

    tomcat目录中-conf文件夹下 <Host name="www.xxx.com" appBase="webapps" unpackWARs=&quo ...

  5. Computer Vision_33_SIFT:PCA-SIFT A More Distinctive Representation for Local Image Descriptors——2004

    此部分是计算机视觉部分,主要侧重在底层特征提取,视频分析,跟踪,目标检测和识别方面等方面.对于自己不太熟悉的领域比如摄像机标定和立体视觉,仅仅列出上google上引用次数比较多的文献.有一些刚刚出版的 ...

  6. SVN 执行cleanup报错:Cleanup failed to process the following paths

    SVN 执行cleanup报错:Cleanup failed to process the following paths 先来说下这个错误的原因:用SVN在使用过程中,各种原因中途取消或中断,导致需 ...

  7. jdk在window系统中的配置

    其实配置很简单,百度上很多配置的复杂化了,今天办公室的某小白百度了半天也没有配置好.   我使用的是Linux ,就很多简单了很多编译器都是集成的,尤其是现在kali linux 系统觉得做得越来也好 ...

  8. Django中使用xadmin作为后台管理页面

    xadmin后台管理 安装:luffy虚拟环境下 # >: pip install https://codeload.github.com/sshwsfc/xadmin/zip/django2 ...

  9. jpa 如果返回java对象,会自动更新对象值(坑!!)

    //上一段示例代码List<Member> memberList = memberDao.findByLoginNameIn(names);for (Member m : memberLi ...

  10. Java集合--Vector

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3308833.html 第1部分 Vector介绍 Vector简介 Vector 是矢量队列,它是JDK ...