题目链接
\(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();
}
};