关于递增子序列问题

关于一个数组的最大递增子序列的个数,首先有一个特别容易理解的方法。

用dp的思想去找以下标i结束的最大递增递减序列个数。持续更新状态;

o(n^2); 时间复杂度高,有些题不能满足。

int o[N],dp[N];//o为数组 dp以下标i结尾的最大子序列长度初值都为1
//因为每个数自身就是一个数列

for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
{
if(o[i]>o[j]) dp[i]=max(dp[i],dp[j]+1);//递增
/*
if(o[i]<o[j]) dp[i]=max(dp[i],dp[j]+1);//递减
*/
}
/*
所有的求完之后再遍历一遍找出最大值就行
也可以和dp过程合并;
*/

还有一种时间复杂度为o(n*logn),应该也是目前一个好的算法。

*********************************************************************************************************

再说之前先补充一个知识点 

p=lower_bound(o,o+n,a)-o;
//p就相当于用二分查找数组o中第一个大于等于a的数的下标,

p=upper_bound(o,o+n,a)-o;
//p就相当于用二分查找数组o中第一个大于a的数的下标,

这两个就差一个等号

p=lower_bound(o,o+n,a,greater<int>())-o;
//p就相当于用二分查找数组o中第一个小于等于a的数的下标,

p=upper_bound(o,o+n,a,greater<int>())-o;
//p就相当于用二分查找数组o中第一个小于a的数的下标,

不过有一部分大佬觉得手动模拟的比这个稍微快一点。

在这的基础上就更方便实现这个子序列

这个东西也是很方便的,在平常做题也是一个很好的选择,而且二分算法是比较省时间的,特别是一些多实例,

***********************************************************************************************************

然后就是这个问题的核心代码,建议认真看。

int o[N];//数组
int dp[N];//状态存储
int len=1;//最大子序列的长度

//先把第一个数放进去
dp[1]=o[1];

for(int i=2;i<=n;i++)
{
   if(o[i]>dp[len]) dp[++len]=o[i];//符合情况直接放入dp
   else 
   {
   int p=lower_bound(dp+1,dp+1+len,o[i])-dp;//找出dp中第一个大于等于o[i]的数的下标
   dp[p]=o[i];//用o[i]替换
   }
}

cout<<len<<endl;//len就是所求的最大长度

/*如过求的是递减、最大不增加、最大不减少序列,只需要稍微改动即可

如果一下看不懂,推荐自己模拟一下这个代码的运行过程,更好的去理解,然后自己手动敲一次代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值