DP之最长递增序列(利用二分查找,复杂度为nlgn)

注意:最长不减子序列的个数 = = 最长递减子序列的长度

      最长不增子序列的个数 = = 最长递增子序列的长度

         最长递增子序列的个数 = = 最长不增子序列的长度

         最长递减子序列的个数 = = 最长不减子序列的长度

#include <iostream>

 

using namespace std;

#define N 1001

int data[N],f[N],dp[N],p[N],e=0;//data数组保存数据,dp有序序列的长度数组,f辅助数组,p保存路径

int bsearch(int *f,int size,int t)//二分查找,复杂度logn

{                               //找出f数组中第一个比t大的数的下标

   int l=0,r=size-1;

   while(l<=r)

    {

       int mid=(l+r)/2;

       if(t>f[mid-1]&&t<=f[mid])return mid;//最长不减子序列,换为>=&&<,递减,<&&>=,不增,<=&&>

       else if(t<f[mid])r=mid-1;

       else l=mid+1;

    }

   return -1;

}

int LIS(int *data,int n)

{

   int i,j,size =1;//size是f数组的大小

   f[0]=data[0];dp[0]=1;p[0]=-1;//第一个点

   for(i=1;i<n;i++)

    {

       //如果data比f数组中最小的还小,则以该点为末尾点的数组的长度为0+1=1;f数组中数据是递增的且保存的是data中数据最小的元素集合

       if(data[i]<=f[0])j=0;//最长不减子序列,<,递减,>=,不增,>

       else if(data[i]>f[size-1])j=size++;//最长不减子序列,>=,递减,<,不增,<=

       else j=bsearch(f,size,data[i]);// 找出f数组中第一个比data[i]大的元素的下标j,则以该点为末尾点的数组的长度为j+1;

       f[j]=data[i];dp[i]=j+1;

       //若求路径则取消注释

//       if(j==0)p[i]=-1;//求p,求最长有序序列的长

//       else

//       {

//            for(int k=0;k<i;k++)

//            {

//                if(data[k]==f[j-1])

//                {

//                    p[i]=k;

//                }

//            }

//       }

//       if(dp[i]==size)e=i; //保存长度最长的有序序列的末尾点的下标

    }

   return size;

}

void printLIS(int e)//输出路径

{

   if(p[e]!=-1)printLIS(p[e]);

   cout<<data[e]<<endl;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值