两种算法
一、传统的思路
使用两重循环,对序列进行遍历:
for(int i=0;i<n;i++)
{
for(int j=i-1;j>=0;j--)
if(num[j]<num[i])
dp[i]=max(dp[j]+1,dp[i]);
}
dp[i]表示从0~i中的最大递增子序列,因此遍历时只需要查找在i之前比num[i]小的数
该方法的时间复杂度为O(n*n)
二、栈优化
当数据规模增大时,传统方法就会出现超时,因此采用堆栈的方法对递增子序列查找进行优化。
//stk 为stack
for(int i=1;i<n;i++)
if(num[i]>stk.top()) stk.push_back(num[i]);//比栈顶大时,直接加入
else{//比栈顶小时,替换第一个比自己大的数字
*lower_bound(stk.begin(), stk.end(), arr[i]) = arr[i];
}
完整的优化详细代码如下:
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
const int N=100010;
int num[N];
int q[N];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>num[i];
int len=0;
q[0]=-1e9-10;
for(int i=0;i<n;i++)
{
int l=0,r=len+1;
while(l<r){
int mid=(l+r)>>1;
if(q[mid]>=num[i]) r=mid;
else l=mid+1;
}
len=max(len,l);
q[l]=num[i];
}
cout<<len<<endl;
}