【算法】子集(LIS最长上升子序列)

文章目录

    • 题目
    • 输入描述
    • 输出描述
    • 示例
    • 分析
    • 思路
    • 最长递增子序列
    • dp解法(2/10)
    • binarySearch + 贪心(AC)

题目

小强现在有 n n n个物品,每个物品有两种属性 x i x^i xi y i y^i yi。他想要从中挑出尽可能多的物品满足以下条件:对于任意两个物品 i i i j j j,满足 x i < x j 且 y i < y j x^i < x^j 且 y^i < y^j xi<xjyi<yj或者 x i > x j 且 y i > y j x^i > x^j 且 y^i > y^j xi>xjyi>yj. 问最多能够挑出多少物品

输入描述

第一行输入一个正整数 T T T.表示有 T T T组数据.
对于每组数据,第一行输入一个正整数 n n n.表示物品个数.
接下来两行,每行有 n n n个整数.
第一行表示 n n n个节点的 x x x属性.
第二行表示 n n n个节点的 y y y属性.

1 < = T < = 10 2 < = n < = 100000 0 < = x , y < = 1000000000 1 <= T <= 10\\ 2 <= n <= 100000\\ 0<= x, y <= 1000000000 1<=T<=102<=n<=1000000<=x,y<=1000000000

输出描述

输出 T T T行,每一行对应每组数据的输出.

示例

输入例子:
2
3
1 3 2
0 2 3
4
1 5 4 2
10 32 19 21
输出例子:
2
3

分析

这题看上去比较绕,我们先以示例入手,简单拆解一下

在这里插入图片描述

现在,我们将目光聚焦于绿框部分,如下图所示

在这里插入图片描述

我们需要选出若干个红框,使得红框组成x属性严格递增的序列时,同时保证y属性也严格递增。且选择红框数量尽可能大

例如,我们选择1,3红框,能够实现双递增序列:
1 -> 3
0 -> 2

2,3红框无法实现双递增序列:
2 -> 3
3 -> 2
(红框元素被绑定死,不能随意组合x,y中任意下标的元素)

如果我们选择1,2,3红框,无法实现递增序列,因为2,3无法形成双递增序列

思路

  1. 设计数据结构,将x,y对应下标元素组合再一起。例如构建如下数据结构
    class Node {
    	public int x;
    	public int y;
    }
    Node[] nodes = new Node[N];
    
  2. 对Node的x属性排序,保证nodes按照x非递减排序
  3. 对排序后的y属性进行筛选,选出最长递增子序列

tip: 此处需要注意,nodes无法按照x严格递增。因为可能存在若干个具有相同x值的node。因此在排序时,如果x相同,需要按照y降序排序。因为这样在对y进行筛选时,在x相同情况下,只能选择一个y最为最终序列。
例如:
1 9 9
3 8 7
最终会只能选择3, 8 | 3,7。如果x相同,但是不按照y降序,则可能会选择3,7,8.导致重复选择相同的x,而无法保证x严格递增

最长递增子序列

目前有两种解法

  1. dp
  2. binarySearch + 贪心

dp和bs算法已经有非常多成熟的文章,感兴趣的读者可以自行了解上述两篇文章,本文只给出ac代码

dp解法(2/10)

import java.util.*;

public class Main {

    static class Node {
        public int x;
        public int y;
        public Node() {}
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        int n;
        for (int i = 0; i < T; ++i) {
            n = sc.nextInt();
            Node[] x = new Node[n];
            // 存储 x - y
            for (int j = 0; j < n; ++j) {
                Node node = new Node();
                node.x = sc.nextInt();
                x[j] = node;
            }
            for (int j = 0; j < n; ++j) {
                x[j].y = sc.nextInt();
            }
            // 排序
            Arrays.sort(x, (Node a, Node b) -> {
                if (a.x != b.x) return a.x - b.x;
                else return - (a.y - b.y);
            });
            int[] y = new int[n];
            for (int j = 0; j < n; ++j) {
                y[j] = x[j].y;
            }
            // 求最长递增子序列
            int[] dp = new int[n];
            dp[0] = 1;
            int maxn = 1;
            for (int j = 1; j < n; ++j) {
                dp[j] = 1;
                for (int k = 0; k < j; ++k) {
                    if (y[j] > y[k]) dp[j] = Math.max(dp[j], dp[k] + 1);
                }
                maxn = Math.max(maxn, dp[j]);
            }
            System.out.println(maxn);
        }
    }
}

在这里插入图片描述

binarySearch + 贪心(AC)

import java.util.*;

public class Main {

    static class Node {
        public int x;
        public int y;
        public Node() {}
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        int n;
        for (int i = 0; i < T; ++i) {
            n = sc.nextInt();
            Node[] x = new Node[n];
            // 存储 x - y
            for (int j = 0; j < n; ++j) {
                Node node = new Node();
                node.x = sc.nextInt();
                x[j] = node;
            }
            for (int j = 0; j < n; ++j) {
                x[j].y = sc.nextInt();
            }
            // 排序
            Arrays.sort(x, (Node a, Node b) -> {
                if (a.x != b.x) return a.x - b.x;
                else return - (a.y - b.y);
            });
            int[] y = new int[n];
            for (int j = 0; j < n; ++j) {
                y[j] = x[j].y;
            }
            // 求最长递增子序列
            int len = 1;
            int[] d = new int[n + 1];
            d[len] = y[0];

            for (int j = 1; j < n; ++j) {
                // y[j] 大于d当前最末尾元素
                if (y[j] > d[len]) {
                    d[++len] = y[j];
                }else {
                    int lef = 1, rig = len, ans = 0;
                    while (lef <= rig) {
                        int mid = (lef + rig) >> 1;
                        if (d[mid] < y[j]) {
                            ans = mid;
                            lef = mid + 1;
                        }else {
                            rig = mid - 1;
                        }
                    }
                    d[ans + 1] = y[j];
                }
            }
            System.out.println(len);
        }
    }
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/481098.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Bootloader/IAP零基础入门(1.0) —— 设计一个Bootloader引导进入APP的程序,不含中断向量偏移

前言 &#xff08;1&#xff09;如果有嵌入式企业需要招聘湖南区域日常实习生&#xff0c;任何区域的暑假Linux驱动/单片机/RTOS的实习岗位&#xff0c;可C站直接私聊&#xff0c;或者邮件&#xff1a;zhangyixu02gmail.com&#xff0c;此消息至2025年1月1日前均有效 &#xff…

重磅消息!《大模型面试宝典》(2024版) 正式发布!

2022 年11月底&#xff0c;OpenAI 正式推出 ChatGPT &#xff0c;不到两个月的时间&#xff0c;月活用户就突破1亿&#xff0c;成为史上增长最快的消费者应用。 目前国内已发布的大模型超过200个&#xff0c;大模型的出现彻底改变了我们的生活和学习方式。 现在只要你想从事 A…

优化选址问题 | 模拟退火算法求解物流选址问题含Matlab源码

目录 问题代码问题 模拟退火算法(Simulated Annealing, SA)是一种概率性的全局优化算法,用于求解大规模组合优化问题。在物流选址问题中,模拟退火算法可以用来寻找成本最低、效率最高的仓库或配送中心位置。下面是一个简化的模拟退火算法求解物流选址问题的描述,并附带有…

阿里云OSS分布式存储

目录 &#x1f9c2;1.OSS开通 &#x1f32d;2.头像上传整合OSS &#x1f68d;2.1.引入依赖 &#x1f68d;2.2添加配置 &#x1f68d;2.3创建配置类 &#x1f68d;2.4添加实现类 &#x1f68d;2.5controller调用接口 &#x1f68d;2.6postman测试 1.OSS开通 1.登…

力扣---最长有效括号---动态规划,栈

动态规划思路&#xff1a; 最长xxxx的问题&#xff0c;从动态规划的角度去考虑&#xff0c;我们会将 g[i] 定义为以 第 i 位 结尾的小问题。在本道题中&#xff0c;我们将 g[i] 定义为以第 i 位为结尾的最长有效括号子串的长度。从头去遍历每一位&#xff0c;我们会发现只有s[i…

我的创作纪念日——在CSDN的三年

我的创作纪念日——在CSDN的三年 个人简介机缘收获个人成就学习成就墙文章专栏 日常成就憧憬 个人简介 &#x1f3d8;️&#x1f3d8;️个人主页&#xff1a;以山河作礼。 &#x1f396;️&#x1f396;️:Python领域新星创作者&#xff0c;CSDN实力新星认证&#xff0c;CSDN内…

134. 加油站(力扣LeetCode)

文章目录 134. 加油站题目描述暴力枚举&#xff08;超时&#xff09;代码一代码二&#xff08;优化&#xff09; 贪心算法方法一方法二 134. 加油站 题目描述 在一条环路上有 n 个加油站&#xff0c;其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车&…

【机器学习入门 】支持向量机

系列文章目录 第1章 专家系统 第2章 决策树 第3章 神经元和感知机 识别手写数字——感知机 第4章 线性回归 第5章 逻辑斯蒂回归和分类 前言 支持向量机(Support Vector Machine) 于1995年发表&#xff0c;由于其优越的性能和广泛的适用性&#xff0c;成为机器学习的主流技术&…

【11】工程化

一、为什么需要模块化 当前端工程到达一定规模后,就会出现下面的问题: 全局变量污染 依赖混乱 上面的问题,共同导致了代码文件难以细分 模块化就是为了解决上面两个问题出现的 模块化出现后,我们就可以把臃肿的代码细分到各个小文件中,便于后期维护管理 前端模块化标准…

活用 C语言之union的精妙之用

一、union的基本定义 Union的中文叫法又被称为共用体、联合或者联合体。它的定义方式与结构体相同,但意义却与结构体完全不同。下面是union的定义格式: union 共用体名 {成员列表}共用体变量名;它与结构体的定义方式相同,但区别在于共用体中的成员的起始地址都是相同的,…

Android Studio Gradle设置查看全部task

如果你在 Android Studio 的 Gradle 窗口中看不到所有的任务&#xff0c;你可以尝试以下步骤来解决这个问题 android studio 版本&#xff1a; Android Studio Iguana | 2023.2.1 Build #AI-232.10227.8.2321.11479570, built on February 22, 2024 打开 Android Studio 的设置…

【CSP】2020-12-3 带配额的文件系统 100分完整代码 最长的大模拟 使用指针优化数据结构

2020-12-3 带配额的文件系统 最长的大模拟 使用指针优化数据结构 索引2020-12-3 带配额的文件系统 最长的大模拟 使用指针优化数据结构思路遇到的问题(学到的东西)40分stl代码acwing 15/15 csp官网40分代码100分完整代码 索引 历年CSP认证考试真题题解总汇持续更新 2020-12-3…

框架结构模态分析/动力时程分析Matlab有限元编程 【Matlab源码+PPT讲义】|梁单元|地震时程动画|结果后处理|地震弹性时程分析| 隐式动力学

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

Bytebase 2.14.1 - 分支 (Branching) 功能支持 Oracle

&#x1f680; 新功能 分支 (Branching) 功能支持 Oracle。为 SQL 编辑器添加了项目选择器。 新增 SQL 审核规范&#xff1a; 禁止混合 DDL、DML 语句。禁止对同一张表进行不同类型的 DML 变更 (UPDATE,INSERT,DELETE)。 &#x1f514; 重大变更 工作空间设置中的「数据访问…

【Linux操作系统】命令的运行原理

文章目录 shell命令以及运行原理Linux系列学习目录 shell命令以及运行原理 Linux严格意义上说的是一个操作系统&#xff0c;我们称之为“核心&#xff08;kernel&#xff09;“ &#xff0c;但我们一般用户&#xff0c;不能直接使用kernel。而是通过kernel的“外壳”程序&…

【网站项目】294火车票订票系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Data Interpreter: An LLM Agent For Data Science 论文解读

论文地址&#xff1a;https://arxiv.org/abs/2402.18679 Github&#xff1a;MetaGPT: The Multi-Agent Framework 数据解释器&#xff08;Data Interpreter&#xff09;是一个基于大型语言模型&#xff08;LLM&#xff09;的代理&#xff0c;专门为解决数据科学问题而设计。它…

主干网络篇 | YOLOv8更换主干网络之MobileNetV3

前言:Hello大家好,我是小哥谈。MobileNetV3是一种轻量级的卷积神经网络架构,用于图像分类和目标检测任务。它是MobileNet系列的第三个版本,旨在在保持高准确性的同时减少模型的计算量和参数数量。MobileNetV3引入了一些新的设计思想和技术,以提高模型的性能。其中一项重要…

抖音用户主页如何打开词令抖音小程序?

抖音用户主页如何打开词令抖音小程序&#xff1f; 1、打开抖音主页&#xff0c;点击右上角的「搜索」&#xff1b; 2、使用抖音搜索找到小程序名称&#xff1a;词令的用户&#xff0c;并点击头像名称进入&#xff1b; 3、进入词令抖音用户主页&#xff0c;并到抖音小程序的图标…

Tensorflow 2.0 常见函数用法(一)

文章目录 0. 基础用法1. tf.cast2. tf.keras.layers.Dense3. tf.variable_scope4. tf.squeeze5. tf.math.multiply 0. 基础用法 Tensorflow 的用法不定期更新遇到的一些用法&#xff0c;之前已经包含了基础用法参考这里 &#xff0c;具体包含如下图的方法&#xff1a; 本文介…