zoukankan      html  css  js  c++  java
  • 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^2

    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;
        }
    };
    
  • 相关阅读:
    AtCoder Beginner Contest 218 A~F 题解
    【学习笔记】光速幂
    【Nowcoder 1103A】复读数组
    【Nowcoder 1105A】集合统计
    初赛知识宝典
    KMP算法 next数组模板
    C#链接Windows远程桌面
    帝国cms 修改 上一篇 下一篇样式
    Appweb漏洞复现
    Apereo-cas漏洞复现
  • 原文地址:https://www.cnblogs.com/clear-love/p/11371457.html
Copyright © 2011-2022 走看看