最长递增子序列

252 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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数组对应每个状态。