力扣---300. 最长递增子序列

发布时间 2023-03-22 21:18:35作者: allWu
给你一个整数数组 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
进阶:
    你能将算法的时间复杂度降低到 O(n log(n)) 吗?
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-increasing-subsequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

典型的动态规划。可以想到,到某个位置的最长严格升序子串,可以由前面的某个小于该位置的数的子串长度加1得到。

可以用一个和nums等长的数组来存储到某个位置时符合要求的子串。

以 10,9,2,5,3,7,101,18 为例:

最后的辅助数组应为:0,0,0,1,1,2,3,3(不包含本身)。

动态规划的时间复杂度为O(n^2)

进阶的要求是时间复杂度为:nlog(n)

这个可以利用二分查找来完成,官解看不懂,不写了,下次有机会再看。

动态规划代码:

class Solution {
    public int lengthOfLIS(int[] nums) {
        int res = 0;
        // 辅助数组
        int[] arr = new int[nums.length];
        for (int i = 0; i < nums.length; i ++) {
            for (int j = 0; j < i; j ++) {
                // 题目要求的是严格递增,不包括相等。
                if (nums[j] < nums[i]) {
                    arr[i] = Math.max(arr[i], arr[j] + 1);
                    res = Math.max(arr[i], res);
                }
            }
        }
        // 由于我们存储的是到当前位置之前的最长严格递增子串的长度,不包括当前节点,所以我们需要+1处理,使之包含当前节点。
        return res + 1;
    }
}