class072 最长递增子序列问题与扩展【算法】

class072 最长递增子序列问题与扩展【算法】

在这里插入图片描述
在这里插入图片描述

code1 300. 最长递增子序列

// 最长递增子序列和最长不下降子序列
// 给定一个整数数组nums
// 找到其中最长严格递增子序列长度、最长不下降子序列长度
// 测试链接 : https://leetcode.cn/problems/longest-increasing-subsequence/

dp[i]:以i位置作结尾的最长递增子序列长度
返回Max(dp[…])

优化
ends[i]:目前所有长度为i+1的递增子序列的最小结尾
返回len

code1 动态规划
code2 优化

package class072;// 最长递增子序列和最长不下降子序列
// 给定一个整数数组nums
// 找到其中最长严格递增子序列长度、最长不下降子序列长度
// 测试链接 : https://leetcode.cn/problems/longest-increasing-subsequence/
public class Code01_LongestIncreasingSubsequence {// 普通解法的动态规划// 时间复杂度O(n^2),数组稍大就会超时public static int lengthOfLIS1(int[] nums) {int n = nums.length;int[] dp = new int[n];int ans = 0;for (int i = 0; i < n; i++) {dp[i] = 1;for (int j = 0; j < i; j++) {if (nums[j] < nums[i]) {dp[i] = Math.max(dp[i], dp[j] + 1);}}ans = Math.max(ans, dp[i]);}return ans;}// 最优解// 时间复杂度O(n * logn)public static int lengthOfLIS2(int[] nums) {int n = nums.length;int[] ends = new int[n];// len表示ends数组目前的有效区长度// ends[0...len-1]是有效区,有效区内的数字一定严格升序int len = 0;for (int i = 0, find; i < n; i++) {find = bs1(ends, len, nums[i]);if (find == -1) {ends[len++] = nums[i];} else {ends[find] = nums[i];}}return len;}// "最长递增子序列"使用如下二分搜索 :// ends[0...len-1]是严格升序的,找到>=num的最左位置// 如果不存在返回-1public static int bs1(int[] ends, int len, int num) {int l = 0, r = len - 1, m, ans = -1;while (l <= r) {m = (l + r) / 2;if (ends[m] >= num) {ans = m;r = m - 1;} else {l = m + 1;}}return ans;}// 如果求最长不下降子序列,那么使用如下的二分搜索 :// ends[0...len-1]是不降序的// 在其中找到>num的最左位置,如果不存在返回-1// 如果求最长不下降子序列,就在lengthOfLIS中把bs1方法换成bs2方法// 已经用对数器验证了,是正确的public static int bs2(int[] ends, int len, int num) {int l = 0, r = len - 1, m, ans = -1;while (l <= r) {m = (l + r) / 2;if (ends[m] > num) {ans = m;r = m - 1;} else {l = m + 1;}}return ans;}}

code2 354. 俄罗斯套娃信封问题

// 俄罗斯套娃信封问题
// 给你一个二维整数数组envelopes ,其中envelopes[i]=[wi, hi]
// 表示第 i 个信封的宽度和高度
// 当另一个信封的宽度和高度都比这个信封大的时候
// 这个信封就可以放进另一个信封里,如同俄罗斯套娃一样
// 请计算 最多能有多少个信封能组成一组“俄罗斯套娃”信封
// 即可以把一个信封放到另一个信封里面,注意不允许旋转信封
// 测试链接 : https://leetcode.cn/problems/russian-doll-envelopes/

排序策略:宽度从小到大;宽度一样,高度从大到小
构成高度数组,求最长递增子序列的长度

package class072;import java.util.Arrays;// 俄罗斯套娃信封问题
// 给你一个二维整数数组envelopes ,其中envelopes[i]=[wi, hi]
// 表示第 i 个信封的宽度和高度
// 当另一个信封的宽度和高度都比这个信封大的时候
// 这个信封就可以放进另一个信封里,如同俄罗斯套娃一样
// 请计算 最多能有多少个信封能组成一组“俄罗斯套娃”信封
// 即可以把一个信封放到另一个信封里面,注意不允许旋转信封
// 测试链接 : https://leetcode.cn/problems/russian-doll-envelopes/
public class Code02_RussianDollEnvelopes {public static int maxEnvelopes(int[][] envelopes) {int n = envelopes.length;// 排序策略:// 宽度从小到大// 宽度一样,高度从大到小Arrays.sort(envelopes, (a, b) -> a[0] != b[0] ? (a[0] - b[0]) : (b[1] - a[1]));int[] ends = new int[n];int len = 0;for (int i = 0, find, num; i < n; i++) {num = envelopes[i][1];find = bs(ends, len, num);if (find == -1) {ends[len++] = num;} else {ends[find] = num;}}return len;}public static int bs(int[] ends, int len, int num) {int l = 0, r = len - 1, m, ans = -1;while (l <= r) {m = (l + r) / 2;if (ends[m] >= num) {ans = m;r = m - 1;} else {l = m + 1;}}return ans;}}

code3 2111. 使数组 K 递增的最少操作次数

// 使数组K递增的最少操作次数
// 给你一个下标从0开始包含n个正整数的数组arr,和一个正整数k
// 如果对于每个满足 k <= i <= n-1 的下标 i
// 都有 arr[i-k] <= arr[i] ,那么称 arr 是K递增的
// 每一次操作中,你可以选择一个下标i并将arr[i]改成任意正整数
// 请你返回对于给定的 k ,使数组变成K递增的最少操作次数
// 测试链接 : https://leetcode.cn/problems/minimum-operations-to-make-the-array-k-increasing/

把每一组分出来
求出每一组的最长不下降子序列的长度,
修改长度就是总长度减去最长不下降子序列的长度
每一组的修改长度求和即为答案

package class072;// 使数组K递增的最少操作次数
// 给你一个下标从0开始包含n个正整数的数组arr,和一个正整数k
// 如果对于每个满足 k <= i <= n-1 的下标 i
// 都有 arr[i-k] <= arr[i] ,那么称 arr 是K递增的
// 每一次操作中,你可以选择一个下标i并将arr[i]改成任意正整数
// 请你返回对于给定的 k ,使数组变成K递增的最少操作次数
// 测试链接 : https://leetcode.cn/problems/minimum-operations-to-make-the-array-k-increasing/
public class Code03_MinimumOperationsToMakeArraykIncreasing {public static int MAXN = 100001;public static int[] nums = new int[MAXN];public static int[] ends = new int[MAXN];public static int kIncreasing(int[] arr, int k) {int n = arr.length;int ans = 0;for (int i = 0, size; i < k; i++) {size = 0;// 把每一组的数字放入容器for (int j = i; j < n; j += k) {nums[size++] = arr[j];}// 当前组长度 - 当前组最长不下降子序列长度 = 当前组至少需要修改的数字个数ans += size - lengthOfNoDecreasing(size);}return ans;}// nums[0...size-1]中的最长不下降子序列长度public static int lengthOfNoDecreasing(int size) {int len = 0;for (int i = 0, find; i < size; i++) {find = bs(len, nums[i]);if (find == -1) {ends[len++] = nums[i];} else {ends[find] = nums[i];}}return len;}public static int bs(int len, int num) {int l = 0, r = len - 1, m, ans = -1;while (l <= r) {m = (l + r) / 2;if (num < ends[m]) {ans = m;r = m - 1;} else {l = m + 1;}}return ans;}}

code4 646. 最长数对链

// 最长数对链
// 给你一个由n个数对组成的数对数组pairs
// 其中 pairs[i] = [lefti, righti] 且 lefti < righti
// 现在,我们定义一种 跟随 关系,当且仅当 b < c 时
// 数对 p2 = [c, d] 才可以跟在 p1 = [a, b] 后面
// 我们用这种形式来构造 数对链
// 找出并返回能够形成的最长数对链的长度
// 测试链接 : https://leetcode.cn/problems/maximum-length-of-pair-chain/

按开头有序
ends数组,放数对的最小结尾,查要查数对的开头,第一个比它大的,再更新最小结尾。

package class072;import java.util.Arrays;// 最长数对链
// 给你一个由n个数对组成的数对数组pairs
// 其中 pairs[i] = [lefti, righti] 且 lefti < righti
// 现在,我们定义一种 跟随 关系,当且仅当 b < c 时
// 数对 p2 = [c, d] 才可以跟在 p1 = [a, b] 后面
// 我们用这种形式来构造 数对链
// 找出并返回能够形成的最长数对链的长度
// 测试链接 : https://leetcode.cn/problems/maximum-length-of-pair-chain/
public class Code04_MaximumLengthOfPairChain {public static int findLongestChain(int[][] pairs) {int n = pairs.length;// 数对根据开始位置排序,从小到大// 结束位置无所谓!Arrays.sort(pairs, (a, b) -> a[0] - b[0]);// 结尾的数值int[] ends = new int[n];int len = 0;for (int[] pair : pairs) {int find = bs(ends, len, pair[0]);if (find == -1) {ends[len++] = pair[1];} else {ends[find] = Math.min(ends[find], pair[1]);}}return len;}// >= num最左位置public static int bs(int[] ends, int len, int num) {int l = 0, r = len - 1, m, ans = -1;while (l <= r) {m = (l + r) / 2;if (ends[m] >= num) {ans = m;r = m - 1;} else {l = m + 1;}}return ans;}}

code5 P8776 [蓝桥杯 2022 省 A] 最长不下降子序列

// 有一次修改机会的最长不下降子序列
// 给定一个长度为n的数组arr,和一个整数k
// 只有一次机会可以将其中连续的k个数全修改成任意一个值
// 这次机会你可以用也可以不用,请返回最长不下降子序列长度
// 1 <= k, n <= 10^5
// 1 <= arr[i] <= 10^6
// 测试链接 : https://www.luogu.com.cn/problem/P8776
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
// 提交以下的所有代码,并把主类名改成"Main",可以直接通过

    		   [k个z]  	z
0   		i       	j
最后小于z的 	+k 		+包含j位置的
不下降子序列的长度     不下降子序列的长度

包含j位置的不下降子序列的长度等同于求出n-1…j的最长不上升子序列
ends存放最大结尾

673. 最长递增子序列的个数
给定一个未排序的整数数组 nums , 返回最长递增子序列的个数 。
测试链接:https://leetcode.cn/problems/number-of-longest-increasing-subsequence/

重剑无锋,大巧不工

package class072;// 有一次修改机会的最长不下降子序列
// 给定一个长度为n的数组arr,和一个整数k
// 只有一次机会可以将其中连续的k个数全修改成任意一个值
// 这次机会你可以用也可以不用,请返回最长不下降子序列长度
// 1 <= k, n <= 10^5
// 1 <= arr[i] <= 10^6
// 测试链接 : https://www.luogu.com.cn/problem/P8776
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
// 提交以下的所有代码,并把主类名改成"Main",可以直接通过import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;public class Code05_LongestNoDecreaseModifyKSubarray {public static int MAXN = 100001;public static int[] arr = new int[MAXN];public static int[] right = new int[MAXN];public static int[] ends = new int[MAXN];public static int n, k;public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));StreamTokenizer in = new StreamTokenizer(br);PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));while (in.nextToken() != StreamTokenizer.TT_EOF) {n = (int) in.nval;in.nextToken();k = (int) (in.nval);for (int i = 0; i < n; i++) {in.nextToken();arr[i] = (int) in.nval;}if (k >= n) {out.println(n);} else {out.println(compute());}}out.flush();out.close();br.close();}public static int compute() {right();int len = 0;int ans = 0;for (int i = 0, j = k, find, left; j < n; i++, j++) {find = bs2(len, arr[j]);left = find == -1 ? len : find;ans = Math.max(ans, left + k + right[j]);find = bs2(len, arr[i]);if (find == -1) {ends[len++] = arr[i];} else {ends[find] = arr[i];}}ans = Math.max(ans, len + k);return ans;}// 生成辅助数组right// right[j] :// 一定以arr[j]做开头的情况下,arr[j...]上最长不下降子序列长度是多少// 关键逻辑 :// 一定以arr[i]做开头的情况下,arr[i...]上最长不下降子序列// 就是!从n-1出发来看(从右往左遍历),以arr[i]做结尾的情况下的最长不上升子序列public static void right() {int len = 0;for (int i = n - 1, find; i >= 0; i--) {find = bs1(len, arr[i]);if (find == -1) {ends[len++] = arr[i];right[i] = len;} else {ends[find] = arr[i];right[i] = find + 1;}}}// 求最长不上升子序列长度的二分// ends[0...len-1]是降序的,找到<num的最左位置// 不存在返回-1public static int bs1(int len, int num) {int l = 0, r = len - 1, m, ans = -1;while (l <= r) {m = (l + r) / 2;if (ends[m] < num) {ans = m;r = m - 1;} else {l = m + 1;}}return ans;}// 求最长不下降子序列长度的二分// ends[0...len-1]是升序的,找到>num的最左位置// 不存在返回-1public static int bs2(int len, int num) {int l = 0, r = len - 1, m, ans = -1;while (l <= r) {m = (l + r) / 2;if (ends[m] > num) {ans = m;r = m - 1;} else {l = m + 1;}}return ans;}}

2023-11-09 20:58:41

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

你知道MySQL中 group by 怎么优化吗

更好的阅读体验&#xff0c;请点击 YinKai s Blog。 ​ 在 MySQL 中 group by 用于按照一个或多个列对结果集进行分组。在讨论 group by 怎么优化之前&#xff0c;我们先来看看 group by 的执行流程&#xff0c;这样我们才能对症下药。 group by 执行流程 ​ 我们先用下面的 …

Ubuntu 18.04使用Qemu和GDB搭建运行内核的环境

安装busybox 参考博客&#xff1a; 使用GDBQEMU调试Linux内核环境搭建 一文教你如何使用GDBQemu调试Linux内核 ubuntu22.04搭建qemu环境测试内核 交叉编译busybox 编译busybox出现Library m is needed, can’t exclude it (yet)的解释 S3C2440 制作最新busybox文件系统 https:…

2024年网络安全竞赛-Web安全应用

Web安全应用 (一)拓扑图 任务环境说明: 1.获取PHP的版本号作为Flag值提交;(例如:5.2.14) 2.获取MySQL数据库的版本号作为Flag值提交;(例如:5.0.22) 3.获取系统的内核版本号作为Flag值提交;(例如:2.6.18) 4.获取网站后台管理员admin用户的密码作为Flag值提交…

udp多播组播

import socket ,struct,time# 组播地址和端口号 MCAST_GRP 239.0.0.1 MCAST_PORT 8888 # 创建UDP socket对象 sock socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) # 绑定socket对象到本地端口号 # sock.bind((MCAST_GRP, MCAST_PORT)) …

【4】PyQt输入框

1. 单行文本输入框 QLineEdit控件可以输入单行文本 from PyQt5.QtWidgets import QApplication, QWidget, QLineEdit, QVBoxLayout from PyQt5.QtCore import * from PyQt5.QtGui import QIcon import sysdef init_widget(w: QWidget):# 修改窗口标题w.setWindowTitle(单行输…

前端面试——CSS面经(持续更新)

1. CSS选择器及其优先级 !important > 行内样式 > id选择器 > 类/伪类/属性选择器 > 标签/伪元素选择器 > 子/后台选择器 > *通配符 2. 重排和重绘是什么&#xff1f;浏览器的渲染机制是什么&#xff1f; 重排(回流)&#xff1a;当增加或删除dom节点&…

【面试经典150 | 二叉树】从中序与后序遍历序列构造二叉树

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;递归 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容…

Android : Room 数据库的基本用法 —简单应用

1.Room介绍&#xff1a; Android Room 是 Android 官方提供的一个持久性库&#xff0c;用于在 Android 应用程序中管理数据库。它提供了一个简单的 API 层&#xff0c;使得使用 SQLite 数据库变得更加容易和方便。 以下是 Android Room 的主要特点&#xff1a; 对象关系映射…

9.MySQL 索引

目录 ​​​​​​​概述 概念&#xff1a; 单列索引 普通索引 创建索引 查看索引 删除索引 唯一索引 创建唯一索引 删除唯一索引 主键索引 组合索引 创建索引 全文索引 概述 使用全文索引 空间索引 内部原理 相关算法&#xff1a; hash算法 二叉树算法 …

Spring基于XML文件配置AOP

AOP AOP&#xff0c;面向切面编程&#xff0c;是对面向对象编程OOP的升华。OOP是纵向对一个事物的抽象&#xff0c;一个对象包括静态的属性信息&#xff0c;包括动态的方法信息等。而AOP是横向的对不同事物的抽象&#xff0c;属性与属性、方法与方法、对象与对象都可以组成一个…

12.10多种编码方式,编码方案选择策略(递归级联),PDE,RLE代码

作者如何选择和设计编码方案&#xff0c;以实现高效的解压缩和高压缩比&#xff1f;BtrBlocks是否适用于所有类型的数据&#xff1f; 选择和设计编码方案&#xff1a; 结合多种高效编码方案&#xff1a;BtrBlocks 通过选择一组针对不同数据分布的高效编码方案&#xff0c;实现…

js判断是否对象自身为空

文章目录 一、前言二、JSON.stringify三、for in 配合 hasOwnProperty四、Object.keys五、Object.getOwnPropertyNames六、Object.getOwnPropertyNames 结合 Object.getOwnPropertySymbols七、Reflect.ownKeys八、最后 一、前言 如何判断一个对象为空&#xff1f; 先上结论&a…

MySql复习笔记03(小滴课堂) 事务,视图,触发器,存储过程

mysql 必备核心知识之事务的详细解析&#xff1a; 创建一个数据库表&#xff1a; 添加数据并开启事务。 添加数据并查询。 登录另一台服务器发现查不到这个表中的数据。 这是因为事务开启了&#xff0c;但是没有提交&#xff0c;只是把数据存到了内存中&#xff0c;还没有写入…

JOSEF 冲击继电器 ZC-23A DC48V 柜内安装,板前带座

系列型号 ZC-23冲击继电器&#xff1b;ZC-23A冲击继电器&#xff1b; ZC-23B冲击继电器 一、用途 冲击继电器ZC-23A DC48V 柜内安装板前带座 (以下简称继电器)&#xff0c;广泛用于直流操作的继电器保护及自动控制回路中&#xff0c;作为集中控制信号元件。 二、主要技术参…

力扣刷题总结 字符串(2)【KMP】

&#x1f525;博客主页&#xff1a; A_SHOWY&#x1f3a5;系列专栏&#xff1a;力扣刷题总结录 数据结构 云计算 数字图像处理 28.找出字符串中第一个匹配项的下标mid经典KMP4593重复的子字符串mid可以使用滑动窗口或者KMP KMP章节难度较大&#xff0c;需要深入理解其中…

Flink 本地单机/Standalone集群/YARN模式集群搭建

准备工作 本文简述Flink在Linux中安装步骤&#xff0c;和示例程序的运行。需要安装JDK1.8及以上版本。 下载地址&#xff1a;下载Flink的二进制包 点进去后&#xff0c;选择如下链接&#xff1a; 解压flink-1.10.1-bin-scala_2.12.tgz&#xff0c;我这里解压到soft目录 [ro…

OrangePi ZERO2 刷机与启动

镜像准备 用读卡器和Win32Diskimager刷写镜像到内存卡&#xff0c;镜像文件见下面百度云链接&#xff1a;https://pan.baidu.com/s/14aKTznc4Jvw4SoFF54JUTg 提取码&#xff1a;1815 刷写完毕后插回香橙派 串口登录 用MobaXterm和USB-TTL进行串口登录&#xff0c;MobaXterm软…

谈一谈网络协议中的应用层

文章目录 一&#xff0c;什么是HTTPHTTP的优缺点HTTPS 一&#xff0c;什么是HTTP 我们在通过网络进行传输数据时&#xff0c;我们要保证&#xff0c;我们在发送时构造的数据&#xff0c;在接收时也能够解析出来&#xff0c;这本质上就是一种协议&#xff0c;是一种应用层协议&…

Spring Cloud + Vue前后端分离-第3章 SpringBoot项目技术整合

Spring Cloud Vue前后端分离-第3章 SpringBoot项目技术整合 3-1 集成持久层框架Mybatis ORM:对象关系映射&#xff0c;Hibernate是全自动ORM&#xff0c;Mybatis是半自动ORM&#xff0c;Mybatis可以操作的花样更多&#xff0c;是首选的持久层框架 System模块集成Mybatis框架…