leetcode 最长上升子序列 动态规划

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

示例:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-increasing-subsequence

算法一:用f[i]表示以下标i结束的最长上升子序列,每次有i个决策,需要在i之前去寻找最长的且比nums[i]小的f[j] ,时间复杂度是n

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        
        //base case
        if(nums.empty())return 0;
        vector<int> f(nums.size());
        f[0]=1;
        int ans=f[0];
        for(int i=1;i<nums.size();++i){
            for(int j=0;j<i;++j){
                if(nums[i]>nums[j])
                    f[i]=max(f[j]+1,f[i]);
                else f[i]=max(f[i],1);
            }
            ans=max(ans,f[i]);
        }
        return ans;
    }
};

算法二:nlogn 这里优化了寻找比当前值小的最长长度,用二分来找,因为我们可以发现若以长度为下标,那么存储的若是nums的值,是具有单调性的,反证法,若后面的小于前面的,那末前面的长度一定比后面的长,出现矛盾,假设错误,找到单调性我们就可以利用二分去寻找比当前值小的最长长度,l=0,r=len;

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> sum(nums.size()+10);
        int len=0;
        sum[0]=-2e9;
        for(int i=0;i<nums.size();++i){
            int l=0,r=len;
            while(l<r){
                int mid=l+r+1>>1;
                if(sum[mid]<nums[i])l=mid;
                else r=mid-1;
            }
            len=max(len,r+1);
            sum[r+1]=nums[i];
        }
        return len;
    }
};

猜你喜欢

转载自www.cnblogs.com/clear-love/p/11371457.html