求最长递增(递减)子序列

最长子序列指的是在一串数字中,求得一个最大的区间,使得这个区间的所有数都是有规律的

一般分为两种,连续与不连续

 

一、连续版

直接从前往后遍历,线性遍历,时间复杂度为O(n)

#include
#define M 100005
using namespace std;
int a[M]={389, 207 ,155 ,300 ,299,170,158, 65},ans=0;
int main()
{
	int sum=1;
	
	for(int i=1;i<8;i++)
	{
		if(a[i]>a[i-1])
			sum++;
		else
			ans=max(ans,sum), sum=1;
	}
	
	cout<

 

二、非连续版

我们以求递增序(不可以相等)列为例

这个时候,就需要另开一个数组ris,用来存放所求的递减序列,分两种情况:

  1. 如果把a[i]放进ris之后,ris任然是递增,把a[i]放进去,长度加1
  2. 如果把a[i]放进去之后,打乱了ris的单调性,这时从ris中找到第一个比a[i]大或者相等的数,用a[i]覆盖

至于lower_bound与upper_bound :  https://blog.csdn.net/qq_41431457/article/details/88919340

#include
#define M 100005
using namespace std;
int a[M]={0,389,207,155,300,299,170,158,65};
int ris[M];
int main()
{
	int len=1;
	ris[1]=a[1];//初始化
	
	for(int i=2;i<8;i++)
	{
		if(a[i]<=ris[len])//找到ris中第一个 >=a[i]的 
			*lower_bound(ris+1,ris+len+1,a[i])=a[i];
		else
			ris[++len]=a[i];
	}
	
	cout<

求递减序列长度:

#include
#define M 100005
using namespace std;
int a[M]={0,389,207,155,300,299,170,158,65};
int dro[M];
bool cmp( int a, int b)
//自定义比较函数,使得lower_bound求的是比第一个目标值小的 
{
	return a>b;
}
int main()
{
	int len=1;
	dro[1]=a[1];//初始化
	
	for(int i=2;i<=8;i++)
	{
		if(a[i]>=dro[len])//找到dro中第一个a[i]小的 
			*lower_bound(dro+1,dro+len+1,a[i],cmp)=a[i];//替换 
		else
			dro[++len]=a[i];
	}
	
	cout<

Dynamic programming:

opt[i] 表示以i结尾的最长序列, 则 面对第i+1个数, 如果这个数比第i个数大, 则再1-i个数中找到一个比a[i] 小的数 ,取最大的opt

    for(int i=1; i<=n; i++)
	{
		opt[i]=1;
		for(int j=1; j

 

你可能感兴趣的:(经典算法)