题目链接

\(O(n^2)\) 做法

用 \(f[i]\) 表示前 \(i\) 位中以第 \(i\) 位作为结尾的 LIS 长度。

转移的方程显然 \(f[j]=\max\{f[i]+1,f[j]\} (i<j,a[i]<a[j])\)

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

\(O(n\log n)\) 做法

\(g[i]\) 代表长度为 \(i+1\) 的 LIS 的最小结尾数

可以考虑到新增一个数的时候,就是在原来的基础上,尽可能的往后增加以后,假设新增的数是 \(x\) ,也就是找到连续的位置 \(a,b\) 使得 \(a<x \le b\) 并更新 \(b\)

寻找的部分用二分实现

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int l=nums.size(),ln=0;
        vector<int> g;
        g.push_back(nums[ln++]);
        for(;ln<l;ln++)
        {
            int start=0,end=g.size()-1,res=-1;
            while(start<=end)
            {
                int mid=(start+end)/2;
                if(g[mid]>=nums[ln])end=mid-1,res=mid;
                else start=mid+1;
            }
            if(res==-1)g.push_back(nums[ln]);
            else g[res]=nums[ln];
        }
        return g.size();
    }
};