• nlogn求解最长上升子序列


    nlogn求解最长上升子序列

    先讲解两个函数 lower_bound()和upper_bound()

    使用规范为

    lower_bound(数组名+k,数组名+k+n,x,cmp)代表在数组[k]到数组[k+n]中查找x  并可以使用重载重新定义cmp  

    upper_bound(数组名+k,数组名+k+n,x,cmp)代表在数组[k]到数组[k+n]中查找x  并可以使用重载重新定义cmp

    两者的区别在于lower_bound()返回的是非降序列的第一个>=key的地址(指针

    而upper_bound()返回的是非降序列的第一个>key的地址(指针

    1.n方时间复杂度的最长上升子序列

    int maxx=0;
    for
    (int i=1;i<=n;i++)//遍历整个数组的数字 {
       dp[i]=1;
    for(int j=1;j<i;j++)//寻找当前最长的上升子序列长度 { if(num[i]>num[j]) dp[i]=max(dp[i],dp[j]+1);//状态转移方程 dp[i]=max(dp[i],dp[j]+1),代表在第i个数时最长上升子序列的长度 如果有更优解就更新dp数组 }
       maxx=max(dp[i],maxx);//维护一个最大值 }

     2.nlogn时间复杂度求解最长上升子序列

    int len=1;
    num[1]=dp[1];
    for(int i=2;i<=n;i++)//遍历整个数组 寻找上升的序列
    {
        if(dp[i]>num[len]){//如果符合条件 将其放入序列末端  
            num[++len]=dp[i];
        }
        else{//如果不符合条件 通过二分 寻找最后一个小于等于这个数的位置 并替换  因为是替换 所以不会影响总序列长度 
            int p=lower_bound(num+1,num+len+1,dp[i])-num;
            num[p]=dp[i];
        }
    }

    这样优化过后  时间复杂度缩减到 n*logn  既外层循环n 内层logn的时间复杂度

    3.nlogn时间复杂度最长不上升子序列

    struct cmp{
        bool operator()(int a,int b){return a>b;}
    };
    
    
    
    for(int i=2;i<=z;i++){
            if(dp1[len1]>=num[i])
                dp1[++len1]=num[i];
            else{
                int p1=upper_bound(dp1+1,dp1+1+len1,num[i],cmp())-dp1;
                dp1[p1]=num[i];
            }
    }
    人十我百 人百我万
  • 相关阅读:
    JVM总结-java基本类型
    JVM总结-虚拟机怎么执行字节码
    spring-BeanDefinition流程源码分析
    spring-BeanFactory源码解析
    linux文件基本权限-基本权限的修改
    Spring-IoC容器初始化流程源码分析
    spring-AOP
    JavaScript笔记 第十六章 匿名函数和闭包
    C# 指针(unsafe与fixed的使用)
    devenv.exe
  • 原文地址:https://www.cnblogs.com/bestcoder-Yurnero/p/10685932.html
Copyright © 2020-2023  润新知