最长上升子序列(O(nlogn))算法并输出最长上升子序列

  1. 最长上升子序列普通算法
    dp[n]表示以a[n]结尾的最长上升子序列长度
    显然有
    dp[n]=max(dp[n],dp[i]+1) 满足a[i]<a[n],1<=i<n
    实现过程时间复杂度为O(n^2)

2.O(nlogn)时间复杂度

思路是用数组lower保存最长上升子序列长度,对于当前元素a[i],若大于数组lower最后一个元素,则插入lower数组。否则,用二分在lower数组找到第一个大于a[i]的元素,并替换a[i]。整体上来说,用了贪心,因为每次的替换是让lower数组每个元素尽可能的小,这样的话就更有可能能在lower数组末尾插入元素。
关键的是,lower数组中保存的元素并不是真正的最长上升子序列,它表示的是最长上升子序列的长度。

那么问题来了?如何求最长上升子序列呢?
我们可以用一个pos2数组,记录一下数组a中的每个元素在lower数组中出现的位置。然后从数组a最后一个元素开始到第一个元素,寻找到最长上升子序列。
具体实现代码如下

int pos2[maxn],answer[maxn];
void LIS_quicker(int arrays[],int lower [],int n){//最长上升子序列nlogn算法+输出最长上升子序列
    lower[1]=arrays[1];
    int index=1;
    pos2[1]=1;
    for(int i=2;i<=n;i++) {
        if(arrays[i]>=lower[index]) {
            lower[++index]=arrays[i];
            pos2[i]=index;
        }else {
            int pos=upper_bound(lower+1,lower+index+1,arrays[i])-lower-1;
            lower[pos]=arrays[i];
            pos2[i]=pos;   //记录原数组中每个元素在 lower数组中出现的位置
        }
    }
    int maxx=999999; //从右往左打印,
    for(int i=n;i>=1;i--) {
        if(index==0) break;
        if(pos2[i]==index&&maxx>a[i]) { //先找第一个在lower数组index位置,再找第一个在lower数组index-1位置直到index=0
            answer[index]=i;//保存答案
            index-=1;
            maxx=a[i];
        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值