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

 

进阶:

  • 你可以设计时间复杂度为 O(n2) 的解决方案吗?
  • 你能将算法的时间复杂度降低到 O(n log(n)) 吗?

 O(NlogN)

class Solution {
    public int lengthOfLIS(int[] nums) {
        int maxL=0;
        int[] dp=new int[nums.length];//所有长度为i+1的递增子序列中, 最小的那个序列尾数.
        //由定义知dp数组必然是一个递增数组, 可以用 maxL 来表示最长递增子序列的长度. 
        for(int num:nums){
            int index=Arrays.binarySearch(dp,0,maxL,num);
            if(index<0)index=-(index+1);
            dp[index]=num;//将num添加入dp数组尾部
            if(index==maxL)maxL++;//表示num比所有已知递增序列的尾数都大,将最长递增序列长度maxL加1
        }
        return maxL;
    }
}

 O(N^2)

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        n=len(nums)
        if n==0:
            return 0
        dp=[1]*n#dp[i] 表示以 nums[i] 结尾的最长上升子序列的长度
        ans=1
        for i in range(n):
            for j in range(i):
                #遍历到 nums[i] 的时候,我们应该把下标区间 [0, ... ,i - 1] 的 dp 值都看一遍
                #如果当前的数 nums[i] 大于之前的某个数,那么 nums[i] 就可以接在这个数后面形成一个更长的上升子序列
                if nums[i]>nums[j]:
                    dp[i]=max(dp[i],dp[j]+1)#把前面的数都看了, dp[i] 就是它们的最大值加 1。即比当前数要小的那些里头,找最大的,然后加 1 。
                    ans=max(ans,dp[i])
        return ans

 

posted @ 2021-03-04 23:49  XXXSANS  阅读(105)  评论(0编辑  收藏  举报