持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
一、题目
LeetCode 最长递增子序列
给你一个整数数组 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数组,那么dp[i]就表示在nums数组中以i位置结尾的子序列的长度,那么这个子序列也是必定包含nums[i]这个元素的。初始的话dp[i]都默认为1,表示每一个位置的元素可以单独组成长度为1的一个子序列。对于dp[i]位置之前的子序列dp[j](0 <= j < i),要保持严格递增那么dp[i]就得大于dp[j],这样以dp[j]结尾的子序列连接上dp[i]之后也是符合递增的了,在这个条件下获取的最大长度的dp[j]加上本身dp[i]的长度或者本身dp[i]的长度中的较大值就是最终dp[i]的值,即dp[i] = max(dp[i], max(dp[j] + 1))。同时需要用一个maxLen变量在更新dp[i]的时候记录下dp[i]中的最大值即是最长递增子序列的长度了,最终遍历完成的maxLen就是最长递增子序列的长度。
三、代码
方法一 Java代码
class Solution {
public int lengthOfLIS(int[] nums) {
int[] dp = new int[nums.length];
int maxLen = 1;
for (int i = 0; i < nums.length; i++) {
dp[i] = 1;
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
maxLen = Math.max(maxLen, dp[i]);
}
return maxLen;
}
}
时间复杂度:O(n^2),首先需要遍历数组的所有元素,然后还要遍历dp数组中最大且符合要求的一个长度。
空间复杂度:O(n),动态规划使用了dp数组对应每个状态。