一个更高效的求最长子序列的算法。
说白了这个算法就是维护一个数组,刚开始的时候这个数组什么都没有。
举个例子:我们给出的数组是a[]={1 7 3 5 9 4 8},然后我们定义一个b数组(维护数组),遵循一个规则,如果a[i]>b数组的最后一个数的话,那么len++,b[len]=a[i];否则,我们就在现有长度的b数组里找出第一个比a[i]大的数,然后用a[i]给他替换掉。最后b数组的长度就是最长上升子序列。
下面是具体的过程:
第一次我们把1给b数组了 b={1}
然后7比1大 b={1,7}
7是第一个大于3的数,用3把7替换掉 b={1 ,3}
5比3大 b={1 3 5}
9比5大 b={1 3 5 9}
5是第一个比4大的数,用4替换5 b={1 3 4 9}
9是第一个大于8的数 用8替换9 b={1 3 4 8}
所以最长上升序列的长度是4
code:
#if 1 //二分
#include<bits/stdc++.h>
using namespace std;
int binary(int val,int a[],int l,int r)
{
int m;
int id;
while(l<=r)
{
m=l+(r-l)/2;
if(a[m]>val)
{
id=m;
r=m-1;
}
else
l=m+1;
}
return id;
}
int main()
{
int a[1000],l,r,len=0;
int b[1000]; //维护数组
int n;
cin>>n;
for(int i=0; i<n; i++)
{
cin>>a[i];
}
b[0]=a[0];
len=1;
for(int i=1; i<n; i++)
{
if(a[i]>b[len-1])
{
len++;
b[len-1]=a[i];
}
else if(a[i]<b[0])
{
b[0]=a[i];
}
else
{
int id=binary(a[i],b,0,len-1);
b[id]=a[i];
}
for(int i=0; i<len; i++)
cout<<b[i]<<" ";
cout<<endl;
}
cout<<len<<endl;
for(int i=0; i<len; i++)
cout<<b[i]<<" ";
}
#endif
#if 0 //调用STL函数lower_bound()实现二分,查找第一个比k大的数
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[1000],l,r,len=0;
int b[1000]; //维护数组
int n;
cin>>n;
for(int i=0; i<n; i++)
{
cin>>a[i];
}
b[0]=a[0];
len=1;
for(int i=1; i<n; i++)
{
if(a[i]>b[len-1])
{
len++;
b[len-1]=a[i];
}
else
{
*lower_bound(b,b+len,a[i])=a[i];
}
for(int i=0; i<len; i++)
cout<<b[i]<<" ";
cout<<endl;
}
cout<<len<<endl;
for(int i=0; i<len; i++)
cout<<b[i]<<" ";
}
#endif