最长单调递增子序列的三种解法

最长递增子序列 一、题目描述 描述: N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学不交换位置就能排成合唱队形。  合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1, 2, …, K,他们的身高分别为T1, T2, …, TK,则他们的身高满足T1 Ti+1 > … > TK (1 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩 阅读详情
问题描述:

找出由n个数组成的序列的最长单调递增子序列

解法一:转化成LCS问题求解,时间复杂度为O(n*n).

思路:原序列为A,把A按升序排序得到序列B,求出A,B序列的最长公共子序列,即为A的最长单调递增子序列。

#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
using namespace std;
//转化成LCS问题,时间复杂度O(n*n)
int d[105][105];
int a[105];
int b[105];
int c[105][105];

void LCS_path(int i,int j)   //打印路径
{
    if(i==0||j==0) return;
    if(c[i][j]==1)
    {
        LCS_path(i-1,j-1);
        cout<<a[i]<<" ";  //a[i]==b[j]

    }
    else if(c[i][j]==2)
    {
        LCS_path(i-1,j);
    }
    else
    {
        LCS_path(i,j-1);
    }
}

int main()
{
    int i,j,n,m;
    //freopen("d:\\test.txt","r",stdin);
    cin>>m;
    while(m--)
    {
        cin>>n;
        for(i=1; i<=n; i++)
        {
            cin>>a[i];
            b[i]=a[i];
        }
        sort(b+1,b+n+1);
        for(i=1; i<=n; i++)
        {
            for(j=1; j<=n; j++)
            {
                if(a[i]==b[j])
                {
                    d[i][j]=1+d[i-1][j-1];
                    c[i][j]=1;
                }
                else if(d[i-1][j]>d[i][j-1])
                {
                    d[i][j]=d[i-1][j];
                    c[i][j]=2;
                }
                else
                {
                    d[i][j]=d[i][j-1];
                    c[i][j]=3;
                }
            }
        }
        LCS_path(n,n);
        cout<<endl;
        cout<<d[n][n]<<endl;
    }
    //fclose(stdin);
    return 0;
}

解法二:设d[i]为以第i个元素结尾的最长递增子序列的长度,则d[i]=max{0,d[j] | j<i,a[j]<a[i]}+1,ans=max{d[i]}.   时间复杂度O(n*n)

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;

int d[105];
int a[105];

int main()
{
    int i,j,n,m;
    //freopen("d:\\test.txt","r",stdin);
    cin>>m;
    while(m--)
    {
        cin>>n;
        for(i=0; i<n; i++)
        {
            cin>>a[i];
        }
        d[0]=1;
        int ans=0;
        for(i=1;i<n;i++)
        {
            int Max=0;
            for(j=i-1;j>=0;j--)
            {
                if(a[i]>a[j])
                {
                    if(Max<d[j]) Max=d[j];
                }
            }
            d[i]=Max+1;
            ans=max(ans,d[i]);
        }
        cout<<ans<<endl;
    }
    //fclose(stdin);
    return 0;
}

解法三:设d[i]为以第i个元素结尾的最长递增子序列的长度。假设已经计算出的两个状态p和q满足a[p]<a[q],且d[p]=d[q],对于后续所有状态(i>p且i>q)来说,p一定比q好。所以此时只保留p一定不会丢失最优解。所以对于相同的d值,只需保留a[i]最小的一个。g[i]表示d值为i的最小状态编号(g[i]初始化为正无穷)。

在给定状态 i 时,可用二分查找找到满足g[k]>=a[i]的第一个下标k,d[i]=k,此时a[i]<g[k],而d[i]=k,所以更新g[k]=a[i].        时间复杂度O(nlogn).

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int INF=1e9;
int d[105];
int a[105];
int g[105];
int main()
{
    int i,j,n,m;
    //freopen("d:\\test.txt","r",stdin);
    cin>>m;
    while(m--)
    {
        cin>>n;
        for(i=0; i<n; i++)
        {
            cin>>a[i];
        }
        int ans=0;
        for(i=1;i<=n;i++) g[i]=INF; //初始化g[i]
        for(i=0;i<n;i++)
        {
            int k=lower_bound(g+1,g+1+n,a[i])-g;
            d[i]=k;
            g[k]=a[i];        //更新g[k],使g数组保持最小递增序列(第1~n个元素均为当前可取最小值),不会丢失最优解
            ans=max(d[i],ans);
        }
        cout<<ans<<endl;
    }
    //fclose(stdin);
    return 0;
}



最长单调递增子序列——动态规划算法 题目简介 最长单调递增子序列是一个很经典的问题,他所需要的就是要在整个序列中(序列一般来讲应该是无序的)寻找出一个最长的升序子序列,这个子序列中的所有元素都必须来自这个原序列,它们可以在原序列中是不相邻的,但是它们之间的相对位置是不可以改动的。比如一个序列: (1, 7, 3, 5, 9, 4, 8) 它有一些上升子序列,如(1, 7), (3, 4, 8)等等。在这些子序列中,长度最长的子序列... 阅读详情

相关推荐

最长递增子序列(LIS)的三种算法

最长递增子序列:给定一个长度为N的数组,找出一个最长的单调递增子序列,子序列不一定连续,但初始顺序不能乱。 比如数组A={1,3,4,2,5},其最长递增子序列为1,3,4,5 方法一:最长公共子序列法 对于给定长度为N的数组A: 使数组B为排序后的数组A (O(NlogN)) 求出A与B的最长公共子序列(LCS) (O(N2)) 对求得的公共子序列进行去重 (O(N)...

Irimsky 4317

最长递增子序列(Longest increasing subsequence)

问题定义: 给定一个长度为N的数组A,找出一个最长的单调递增子序列(不要求连续)。 这道题共3种解法。 1. 动态规划 动态规划的核心是状态的定义和状态转移方程。定义lis(i),表示前i个数中以A[i]结尾的最长递增子序列的长度。可以得到以下的状态转移方程: d(i) = max(1, d(j) + 1), 其中j < i,且A[j] <=...

weixin_33817333的博客 285

最长单调递增子序列问题

问题描述:找出n个数的数组中最长单调递增子序列。         解法一:先对数组进行排序,归并、堆、快速等都可以,时间复杂度为O(nlogn)。然后求这个新数组与原数组的最长公共子序列,动态规划解决,时间复杂度为O(n*n)。         解法二:以一个数组记录临时的最长序列,然后记录这个序列中的位置的变化。直接上代码:        void increase_LCS() { co

flywithmj的专栏 1345

HNU_算法_实验3(2021级)-算法实验2-单调递增最长子序列问题

分析题3-2单调递增最长子序列问题:

蟑螂恶霸的博客 1304

最长单调递增子序列LIS

问题:        给出一个长度为n的数组,求出最长公共子序列(不一定连续,但顺序不能乱)。如 数组 {3 ,1,5,2,7  },结果为 {3,5,7}或{1,5,7},长度为3。 解法 一:最长公共子序列           将原数组按升序排序,然后将得到数组与原数组求最长公共子序列,其结果就是最长递增子序列(以下简称LIS)。       如 3 ,1,5,2,7 排序后得到1,2

流沙-岁月 550

模板 - 最长上升子序列与最长公共子序列

整理的算法模板合集: ACM模板 目录1.最长上升子序列(LIS)1.1树状数组优化O(nlogn)O(nlogn)O(nlogn)2.最长公共子序列(LCS)2.1转换成LIS优化O(nlogn)O(nlogn)O(nlogn) 1.最长上升子序列(LIS) 给出一个⻓度为n的数字序列ai{ai}ai,我们需要找到一个最⻓的子序列, 使得子序列中的数字大小单调递增。 例如:n=5n = 5n=5,原序列为(1,4,2,3,5)(1,4,2,3,5)(1,4,2,3,5),那么我们选择(1,2,3,5)(

繁凡さん的博客 3562

[LeetCode解题报告] 926. 将字符串翻转到单调递增

dp或者LIS

liuliangcan的博客 170

三种算法求一个数字序列的最长递增子序列

也有很多博客写如何实现最长递增子序列的算法,自己查阅了一些资料总结出三种实现的算法,两种是常见的处理思路,还有一种是本人自己想出来的算法,很好理解,但是效率不是特别高。 算法一: 将n个数的原序列A[n]排序后得到递增序列B[n],则把求A的最长单调递增子序列问题转化成求A、B序列的最长公共子序列(LCS)。 这个算法是算法导论书后面习题的标准答案解法了,有很多人写过实现。时间复杂度O(n^

zyy_286的博客 6450

单调递增子序列

前言:最长公共子序列 子序列可以不连续,但是有先后的次序关系. 为啥不能使用暴力解决这个问题:设A串长为n, B串长为m。A串子序列个数, B串子序列个数, 针对每一种情况进行匹配,时间复杂度变为: . 所以利用动态规划: A = {a, b, c, 1, 2, 3, a, b, c} B = {1, 2, 3, a, d, c} 定义状态: dp[i][j]: A串第i个位置,B串第...

ysugarr 2400

求取最长递增子序列(MFC编程)

贪心算法、动态规划实现最长递增子序列的求取(MFC编程)。

Spring Boot 构建war 部署到tomcat下无法在Nacos中注册服务

因此,当使用外部容器时,如此处的 Tomcat 来部署项目,AbstractAutoServiceRegistration 就不能监听到容器启动事件了,也就不会尝试向服务注册中心注册当前这个微服务,那么注册就失败了,并且也就没有异常信息了。自定义获取获取外部容器端口的方法, 然后监听应用启动事件,当应用被启动时,获取外部容器启动的端口号,然后将这个 port 设置到 NacosAutoServiceReigistration 中。在启动类同级目录,复制下面代码即可(不需要修改,直接构建war即可)

ttyy1112的专栏 2519

最长递增子序列(Longest Increasing Subsequence)

定义 最长上升子序列(Longest Increasing Subsequence,LIS),在计算机科学上是指一个序列中最长的单调递增的子序列。 问题描述 给定一个长度为 N 的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱)。例如:给定一个长度为 5 的数组{5, 6, 1, 2, 8},则其最长的单调递增子序列为 {5,6,8},长度为 3。 解法 动态规划 时间复杂度 该方法的时间复杂度为 。 实现过程 下面我们用一个实例来分析一下动态规划求解 LIS 的整个过程。

努力中的老周的专栏 4370

ENVI与Sarscape协同处理哨兵一号数据的完整流程解析

本文详细解析了利用ENVI与Sarscape软件协同处理哨兵一号(Sentinel-1)SAR数据的完整工作流程。从环境搭建、数据导入与裁剪,到核心的DEM辅助多时相配准、斑点噪声滤波,再到最终的地理编码与辐射定标,提供了标准化的操作指南与实用技巧,帮助用户高效地将原始雷达数据转化为可用于分析的地理编码产品。

weixin_29251131的博客 339

最长递增子序列的三种算法

转载自:http://qiemengdao.iteye.com/blog/1660229 最长递增子序列   问题 给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱)。例如:给定一个长度为6的数组A{5, 6, 7, 1, 2, 8},则其最长的单调递增子序列为{5,6,7,8},长度为4.   解法1:最长公共子序列法 这个问题可以转换为最长公共子序...

小灰狼与大白兔的博客 3万+

单细胞测序流程(五)t-sne聚类分析和寻找marker基因

系列文章目录 单细胞测序流程(一)简介与数据下载 单细胞测序流程(二)数据整理 单细胞测序流程(三)质控和数据过滤——Seurat包分析,小提琴图和基因离差散点图 单细胞测序流程(四)主成分分析——PCA 本期主讲内容——t-sne聚类分析和寻找marker基因 介绍:T-SNE是一种用于探索高维数据的非线性降维算法。它将多维数据映射到适合于人类观察的两个或多个维度。 一、课前准备 之前所使用的数据 R语言的IDE 二、过程 聚类分析的目的是根据细胞的差别所进行细胞分群,两个..

qq_45478665的博客 2万+

rk3588 Android HDMI IN热插拔解决

1、公司在使用 别的厂商的板卡遇到一个问题,开机我们的app自启就会闪退,后来定位发现是camera 的open出错了,这个问题的出现是因为没有插HDMI IN输入的问题导致的,所以需要对HDMI IN的热插拔进行检测,后面我把这个问题也顺利解决了。下面是我的尝试和使用的解决办法。3、话不多说,我用的是读取系统文件实现的,但是这个方法,需要有status文件的系统读权限,可以修改设备下的/vendor/etc/init/hw/init.rk3588.rc文件修改的权限,这个问题交给自己或者厂家协商解决。

qq_54089476的博客 1920

动态规划之最长单调递增子序列

问题描述: 找出由n个数组成的序列的最长单调递增子序列 解法一: 原序列记为X,对n个数递增排序,构造一个新序列Y, 对X,Y求其最长公共子序列即可. /* * description: 最长单调递增子序列 * 问题描述: * 找出由n个数组成的序列的最长单调递增子序列 * 算法设计: * 解法一: * 原序列记为X,对n个数递增排序,构造一个新序列Y, 对X,Y求...

游骑兵打先锋的专栏 321

STM32 MCU解除读保护的方法及STM32CubeProgrammer的应用

下面是一个简单的源代码示例,演示如何在STM32CubeProgrammer中使用命令行界面(Command-Line Interface,CLI)来解除STM32 MCU的读保护。通过按照这些步骤操作,您可以成功解除STM32 MCU的读保护,并在需要的时候进行调试、烧录或修改固件。模块调用了STM32CubeProgrammer的命令行界面(CLI),并传递了相应的参数来解除STM32 MCU的读保护。请注意,在进行任何与读保护相关的操作之前,请确保您拥有合法的授权和权利,以避免潜在的安全风险。

ZwcCsharp的博客 3550
上一篇: 相对路径和绝对路径的区别
下一篇: DOS命令学习(从入门到精通)
Anonymous-邦
博客等级 码龄13年 67粉丝 94原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值