最长上升子序列

【解析】    

举个例子吧,比如一个数组a[9]={0,1,2,5,3,6,8,7,9}这样一个数组,a[0]是不参与运算的啊,这里我是为了好写,叫你求最长的上升子序列,其实我们可以这么看,定义两个数组b[10],c[10],其实就是这么两个过程,先把a[1]给了b[1],此时b[1]为1,然后c[1]也为1,表示上升子序列长度为1的,元素为1,之后把a[2]给b[2],此时b[2]为2,b[2]>b[1]所以此时上升子序列长度变二c[2]也我为2,之后呢a[3]给b[3],前者显然大于后者所以继续,直到a[4]的时候我们发现a[4]是小于a[3]的,我们其实可以这么想,如果保持上升子序列长度不变,是不是这个序列中前面元素越小,后面才有可能继续变大,不如你一个序列可能是1,2,3,5,4,6那么我们应该怎么选择?肯定是选1,2,3,4,6这个作为最长子序列,而不会选择1,2,3,5是吧就是把小的元素尽量替换掉插进去。此刻替换掉我们就需要有一个二分法来求下界了,因为c这个数组是有序的所以可以二分法,注意二分法必须是有序的序列。求下界的话如果存在相同的就返回出现第一次出现那个元素的下标,没有就返回一个下标插入元素使整个序列任然是有序的。在大佬那里学到了这个算法。

#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
int a[100]={0,1,2,5,3,6,8,7,9},b[100],len;
int facs(int i)
{
    int left=0;int right=len;
    int mid;
    while(left<right)
    {
        mid=left+(right-left)/2;
        if(b[mid]>a[i])
            right=mid;//往左边找
        else
            left=mid+1;//往后面找
    }
    return left;
}
int main()
{
   b[1]=a[1];
   len=1;
   int k;
   for(int i=2;i<=8;i++)
   {
       if(a[i]>b[len])
       {
           b[++len]=a[i];
       }
       else
       {
         k=facs(i);
         b[k]=a[i];
       }
   }
   printf("%d\n",len);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值