leetcode300 最长上升子序列(Medium)

题目来源:leetcode300 最长上升子序列

题目描述:

给定一个无序的整数数组,找到其中最长上升子序列的长度。

示例:

输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
说明:

可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n^2) 。
进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?

解题思路:

动态规划,时间复杂度O(n^2),见代码。

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        if(nums.empty()) return 0;
        int ans=1;
        vector<int> dp(nums.size(),0);//dp[i]表示以nums[i]结尾的前i个字符的最长子序列长度。
        dp[0]=1;
        for(int i=1;i<nums.size();i++){
            int maxVal=0;
            for(int j=0;j<i;j++){
                //必须满足nums[j]<nums[i],才能以nums[i]结尾,在所有满足条件中找出最大的
                if(nums[j]<nums[i]){
                    maxVal=max(dp[j],maxVal);
                }
            }
            dp[i]=maxVal+1;//长度+1
            ans=max(ans,dp[i]);//更新结果
        }
        return ans;
    }
};

复杂度降低到 O(n log n) ,可以使用贪心+二分。(参考链接:讨论区链接

参考代码:

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        if(nums.empty()) return 0;
        int n=nums.size();
        vector<int> dp(n+1,0);
        int len=1;
        dp[len]=nums[0];
        for(int i=1;i<nums.size();i++){
            if(nums[i]>dp[len]) dp[++len]=nums[i];
            else{
                int l=1,r=len,pos=0;// 如果找不到说明所有的数都比 nums[i] 大,此时要更新 d[1],所以这里将 pos 设为 0
                while(l<=r){
                    int mid=l+(r-l)/2;
                    if(dp[mid]<nums[i]) {
                        pos=mid;
                        l=mid+1;
                    }
                    else r=mid-1;
                }
                dp[pos+1]=nums[i];
            }
        }
        return len;
    }
};
原文地址:https://www.cnblogs.com/yjcoding/p/13326526.html