题目链接: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 <= nums.length <= 2500
-104 <= nums[i] <= 104
文章讲解:代码随想录
视频讲解:动态规划之子序列问题,元素不连续!| LeetCode:300.最长递增子序列_哔哩哔哩_bilibili
题解1:动态规划
思路:使用动态规划法求解子序列问题。
动态规划分析:
- dp 数组以及下标的含义:dp[i] 代表以 nums[i] 结尾的最长递增子序列的长度。
- 递推公式:dp[i] = Math.max(dp[i], dp[j] + 1),j < i。
- dp 数组初始化:某个元素结尾的最小递增子序列即为它自己,因此全部初始化为1。
- 遍历顺序:i 从前往后,j 从前到后和从后往前都可以。
- 打印 dp 数组:以输入 [10,9,2,5,3,7,101,18] 为例,dp 数组为 [ 1, 1, 1, 2, 2, 3, 4, 4 ]。
/**
* @param {number[]} nums
* @return {number}
*/
var lengthOfLIS = function(nums) {
const dp = new Array(nums.length).fill(1);
for (let i = 1; i < nums.length; i++) {
for (let j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}
return Math.max(...dp);
};
分析:时间复杂度为 O(n²),空间复杂度为 O(n)。
收获
练习使用动态规划法求解子序列问题,要明确 dp 数组的含义,最后取结果时才能取到正确的结果。