【序列dp】最长上升子序列(一)_最长上升子序列 dp-程序员宅基地

技术标签: 算法  java  蓝桥杯  动态规划  开发语言  

最长上升子序列-序列dp

  • 什么是序列相关的 DP ?
  • 序列相关 DP,顾名思义,就是将动态规划算法用于数组或者字符串上,进行相关具体问题的求解
  • 何时可以使用序列相关的 DP?
  • 当题目求解以下内容时,可以考虑使用序列相关的 DP
  • 给定两个字符串,求最长/大的某种值
  • 给定数组,求最长/大的某种值

此外,在使用序列相关的 DP 的时候,我们还需要注意到,这是一类的动态规划,所以需要满足动态规划的两种重要条件
最长上升子序列问题是一个经典的动态规划问题,目标是在给定序列中找到一个最长的升序子序列。

问题描述:
给定一个序列,要求找到其中最长的一个升序子序列。也就是说,要找到一个子序列,使得其中的元素按照从小到大的顺序排列,并且长度最长。

解决方法:
一种常用的动态规划方法来解决最长上升子序列问题是使用一个辅助数组dp。dp[i]表示以第i个元素结尾的最长上升子序列的长度。

具体步骤如下:

  1. 初始化dp数组为1,所有的元素初始都有一个长度为1的子序列。
  2. 对于每个位置i,从0到i-1遍历前面的元素j:
    • 如果第i个元素大于第j个元素,说明可以将第i个元素添加到以第j个元素结尾的子序列中,形成一个更长的子序列。
      • 此时更新dp[i] = max(dp[i], dp[j] + 1),表示以第i个元素结尾的子序列的长度。
  3. 遍历所有的dp[i],找到其中的最大值max_length,即为最长上升子序列的长度。

最后,根据dp数组的记录,可以逆向构造最长上升子序列的元素。

总结:
最长上升子序列问题可以通过动态规划的方法解决,使用dp数组记录以每个位置结尾的最长上升子序列长度,通过逐个比较元素大小,不断更新dp数组。最终得到最长上升子序列的长度,及其中的元素。这个问题是经典的算法问题,在实际应用中有广泛的应用。

概览

在这里插入图片描述

895 最长上升子序列-O(n^2)

在这里插入图片描述

集合表示:所有以a[i]结尾的最长上升子序列

属性为Max即长度的最大值

考虑如何计算,一般考虑最后一个点,可以取

空,a[0],a[1],…,a[i-1]

但是有的区间为空,当a[k] >= a[i]时,即不满足上升子序列

计算时:a[i]=Math.max(满足条件的a[k])

最终答案,遍历所有下标,选取最长的上升子序列

package acwing_plus.动规.最长上升子序列;

import java.util.Scanner;

/**
 * @author ty
 * @create 2023-03-30 21:35
 */
public class 最长上升子序列 {
    
    static int N = 1010;
    static int[] a = new int[N];
    static int[] f = new int[N];
    static int n;
    public static void main(String[] args) {
    
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        for (int i = 1;i <= n;i++) {
    
            a[i] = sc.nextInt();
        }
        for (int i = 1;i <= n;i++) {
    
            f[i] = 1;
            for (int j = 1;j < i;j++) {
    
                if (a[i] > a[j]) {
    
                    f[i] = Math.max(f[j] + 1,f[i]);
                }
            }
        }
        int res = 0;
        for (int i = 1;i <= n;i++) {
    
            //res是所有不同a[i]结尾的最大值
            res = Math.max(res,f[i]);
        }
        System.out.println(res);
    }
}

1017 怪盗基德的滑翔翼

在这里插入图片描述

在这里插入图片描述

LIS的双向求解,主要掌握求最长下降序列,即反向求解最长上升序列

package acwing_plus.动规.最长上升子序列;

import java.util.Scanner;

/**
 * @author ty
 * @create 2023-03-30 21:57
 */
public class 怪盗基德 {
    
    static int N = 110;
    static int n;
    static int[] a = new int[N];
    static int[] f = new int[N];
    public static void main(String[] args) {
    
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        while (T-- > 0 ) {
    
            n = sc.nextInt();
            for (int i = 1;i <= n;i++) {
    
                a[i] = sc.nextInt();
            }
            //正向求解LIS问题
            int res = 0;
            for (int i = 1;i <= n;i++) {
    
                f[i] = 1;
                for (int j = 1;j < i;j++) {
    
                    if (a[j] < a[i]){
    
                        f[i] = Math.max(f[j] + 1,f[i]);
                    }
                }
                res = Math.max(res,f[i]);
            }
            //反向求解LIS
            for (int i = n;i >= 1;i--) {
    
                f[i] = 1;
                for (int j = n;j > i;j--) {
    
                    if (a[i] > a[j]) {
    
                        f[i] = Math.max(f[i],f[j] + 1);
                    }
                }
                res = Math.max(f[i],res);
            }
            System.out.println(res);
        }
    }
}

1014 登山

在这里插入图片描述

在这里插入图片描述

自己实现,由怪盗基德思想实现

package acwing_plus.动规.最长上升子序列;

import java.util.Scanner;

/**
 * @author ty
 * @create 2023-03-30 23:10
 */
public class 登山 {
    
    static int N = 1010;
    static int[] a = new int[N];
    static int[] l = new int[N];
    static int[] r = new int[N];
    static int n;
    public static void main(String[] args) {
    
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        for (int i = 1;i <= n;i++ ) {
    
            a[i] = sc.nextInt();
        }
        int res = 0;
        //求最长下降子序列长度
        for (int i = n;i >= 1;i-- ) {
    
            r[i] = 1;
            for (int j = n;j > i;j--) {
    
                if (a[i] > a[j]) {
    
                    r[i] = Math.max(r[j] + 1,r[i]);
                }
            }
        }
        //求最长上升子序列长度
        for (int i = 1;i <= n;i++) {
    
            l[i] = 1;
            for (int j = 1;j < i;j++) {
    
                if (a[i] > a[j]) {
    
                    l[i] = Math.max(l[i],l[j] + 1);
                }
            }
        }
        for (int i = 1;i <= n;i++) {
    
            res = Math.max(l[i]+r[i] - 1,res);
        }
        System.out.println(res);
    }
}

482 合唱队形

在这里插入图片描述

登山的变体,求整个队列个数-max(每个点的最大上升序列+最大下降序列-1)

package acwing_plus.动规.最长上升子序列;

import java.util.Scanner;

/**
 * @author ty
 * @create 2023-03-31 0:36
 */
public class 合唱队形 {
    
    static int N = 110;
    static int n;
    static int[] a = new int[N];
    static int[] l = new int[N];
    static int[] r = new int[N];
    public static void main(String[] args) {
    
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        for (int i = 1;i <= n;i++) {
    
            a[i] = sc.nextInt();
        }
        for (int i = 1;i <= n;i++) {
    
            l[i] = 1;
            for (int j = 1;j < i;j++) {
    
                if (a[i] > a[j]) {
    
                    l[i] = Math.max(l[i],l[j] + 1);
                }
            }
        }
        for (int i = n;i >= 1;i--) {
    
            r[i] = 1;
            for (int j = n;j >= i;j--) {
    
                if (a[i] > a[j]) {
    
                    r[i] = Math.max(r[i],r[j] + 1);
                }
            }
        }
        int res = 0;
        for (int i = 1;i <= n;i++) {
    
            res =  Math.max(res,l[i] + r[i] -1);
        }
        System.out.println(n - res);
    }
}

1012 友好城市

在这里插入图片描述

在这里插入图片描述

package acwing_plus.动规.最长上升子序列;

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

/**
 * @author ty
 * @create 2023-03-31 9:40
 */
public class 友好城市 {
    
    static int N = 5010;
    static Edge[] a = new Edge[N];
    static int[] f = new int[N];
    static int INF = (int)-1e9;
    static class Edge {
    
        int u,d;

        public Edge(int u, int d) {
    
            this.u = u;
            this.d = d;
        }
    }
    static int n;
    public static void main(String[] args) {
    
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        for (int i = 1;i <= n;i++) {
    
            int x = sc.nextInt();
            int y = sc.nextInt();
            a[i] = new Edge(x,y);
        }
        //按下面排好序
        Arrays.sort(a, 1, n + 1, new Comparator<Edge>() {
    
            @Override
            public int compare(Edge o1, Edge o2) {
    
                return o1.d - o2.d;
            }
        });
        //上面的点一定是上升序列,才能成立
        //此处寻找最长上升子序列
        for (int i = 1;i <= n;i++) {
    
            f[i] = 1;
            for (int j = 1;j < i;j++) {
    
                if (a[i].u > a[j].u) {
    
                    f[i] = Math.max(f[i],f[j] + 1);
                }
            }
        }
        int res = 0;
        for (int i = 1;i <= n;i++) {
    
            res = Math.max(res,f[i]);
        }
        System.out.println(res);
    }
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Trae1ounG/article/details/131314229

智能推荐

《CCNP TSHOOT 300-135认证考试指南》——6.8节三层EtherChannel故障检测与排除-程序员宅基地

文章浏览阅读213次。本节书摘来自异步社区《CCNP TSHOOT 300-135认证考试指南》一书中的第6章,第6.8节三层EtherChannel故障检测与排除,作者 【加】Raymond Lacoste , 【美】Kevin Wallace,更多章节内容可以访问云栖社区“异步社区”公众号查看6.8 三层EtherChannel故障检测与排除CCNP TSHOOT 3..._eth-port-channel-3-compat_check_failure:port channel lfc-pfc compat chec

ROLAP与大数据-程序员宅基地

文章浏览阅读248次。OLAP大数据相关的场景比较多,常见的有:ETL(数据提取、转换、加载)、实时流式(监控报警、风控等)、机器学习(推荐引擎、用户画像等)、非结构化分析(视频、图片、语音、文本等)、海量大数据在线存储(HBase)、搜索及我们本文讲的OLAP。 其中OLAP(在线联机分析)在很多企业占住分析类的大部分。按照一般的理论又分为,M-OLAP,R-OLAP,H..._rolap包括有维表和

在modelarts上离线安装一些大的whl安装包(下载keras github预训练模型)_keras的whl文件-程序员宅基地

文章浏览阅读761次。我们这里以(320.4 MB) 的 tensorflow_gpu-2.3.0 为例子首先!pip install tensorflow-gpu==2.3.0 -i https://pypi.doubanio.com/simple安装完成后,基本上 whl 也就在 缓存文件夹里了本来 按照 这篇 通过 sudo find 就可以找到,但 华为云里 sudo 需要密码,find 的方法就不行了,那还有没有其他方法呢?还真有。通过下面 三步可以找回。一,先卸载 TF2.3!.._keras的whl文件

Winform Timer控件时间间隔-程序员宅基地

文章浏览阅读769次。2019独角兽企业重金招聘Python工程师标准>>> ..._winform计时器控件间隔1分钟

[号外号外]ios系统中应用webview、safari浏览器cors请求跨域不携带cookie问题解决-程序员宅基地

文章浏览阅读1.7k次。【Android党不必操心此问题】一、问题描述最近手机升级ios11,在做项目测试时,遇到微信webview和safari浏览器cors跨域情况不携带cookie。百度之后,没有找到相关解决办法,经过几天折腾终于解决。直接看问题(1)已登录,其他请求登录超时二、解决办法 (系统设置/Safari/阻止跨网站跟踪.勾掉)(1)系统设置(2)Safari(3)阻止跨网站跟踪..._ios safari 跨域

RSA key lengths-程序员宅基地

文章浏览阅读69次。RSA key lengthsFrom http://www.javamex.com/tutorials/cryptography/rsa_key_length.shtmlWhen you create an RSA key pair, you specify a key length in bits, as generally you would for other algorithms..._rsa key mod len

随便推点

html中什么是框架,什么是css框架-程序员宅基地

文章浏览阅读1.1k次。css框架对于一个小项目等页面来说很臃肿,框架中可能有大部分你用不到的代码。那么你对css框架了解多少呢?下面就让学习啦小编来给你科普一下什么是css框架。css框架的特征1.抽象出常用的css样式,高再可用性,高移植性2.有固有的定义,详细的文档及开发特点3.高兼容性,可以兼容流行的浏览器4.以css为主,但不一定全部是css,可能有一些js(或者其他)脚本用于兼容浏览器css框架的开发顺序a)..._html+css框架是什么

angular基础11【表单】_angular 表单-程序员宅基地

文章浏览阅读930次。在 Angular 中,表单有两种类型,分别为模板驱动和模型驱动。_angular 表单

visual assist x 2406 和 2435,2443 原版安装下载,只要一分_visual ass 2476-程序员宅基地

文章浏览阅读4.5k次,点赞9次,收藏8次。下载地址:https://download.csdn.net/download/zdhsoft/19816256可以用everything找到VA_X.dll,替换就可以了,已经在vs2019下面通过,非飘云版。资源分,只要1分,不是动态调分了_visual ass 2476

android ota 服务器搭建,构建 OTA 软件包  |  Android 开源项目  |  Android Open Source Project...-程序员宅基地

文章浏览阅读1.2k次。您可以使用 build/make/tools/releasetools 中提供的 ota_from_target_files 工具,针对使用 A/B 系统更新或非 A/B 系统更新的设备构建完整 OTA 软件包和增量 OTA 软件包。该工具将 Android 构建系统生成的 target-files.zip 文件作为输入文件。注意:请勿使用或修改(或允许应用使用或修改)/data/ota_pack..._/data/ota_package/

Properties类简介_properties 类-程序员宅基地

文章浏览阅读1.3w次,点赞33次,收藏63次。概述Properties 继承于 Hashtable。表示一个持久的属性集,属性列表以key-value的形式存在,key和value都是字符串。Java中有个比较重要的类Properties(Java.util.Properties),主要用于读取Java的配置文件,各种语言都有自己所支持的配置文件,配置文件中很多变量是经常改变的,这样做也是为了方便用户,让用户能够脱离程序本身去修改相关的变..._properties 类

WIFI基础入门--802.11--直接序列物理层(DSSS)--12_cs/cca-程序员宅基地

文章浏览阅读4.3k次。WIFI基础入门--802.11--直接序列物理层--15直接序列传输2.编码方式直接序列传输直接序列传输时一种不同的扩频技术,可以通过较宽的频带传送信号。直接序列技术的基本运作方式,是通过精确的控制将RF能量分散至某个宽频带。当无线电载波的变动被分散至较宽的频带时,接收器可以通过相关处理找出变动所在。窄带无线电信号经过扩频器的处理后,以数学转换公式将窄带输入信号的振幅平坦化,分布至相对较宽..._cs/cca