最长递增子序列问题(你真的会了吗)

article/2025/9/21 0:25:49

目录

一.最长递增子序列问题I

二.最长递增子序列问题II

三. 最长递增子序列问题III


一.最长递增子序列问题I

1.对应牛客网链接

最长上升子序列(一)_牛客题霸_牛客网 (nowcoder.com)

2.题目描述:

 3.解题思路

1.首先我们分析题意:最长递增子序列拆:要递增的,还是序列,不一定连续 ,要长度最长的。

2.子序列和子数组问题我们一般考虑必须以某个位置结尾如何如何,在本题中我们可以这样考虑必须以i位置结尾的情况下最长递增子序列的最大长度是多少我们每个位置都这么干那么答案一定就在其中

下面以[5,7,1,9,4,6,2,8,3]为例:

第一个元素 5: 递增长度只能为1, 接下来第二个7,比5大,长度为2

 

第三个元素 1:前面没有比它大的,只能为1 , 第四个元素9,前面有5,7,故长度为3到这里你发现,9比7大,7往前构成的长度是2,那9就可以接在7的后面,变成长度加一的新序列。

 我相信老铁应该懂了

4.对应代码:

class Solution {public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** 给定数组的最长严格上升子序列的长度。* @param arr int整型vector 给定的数组* @return int整型*/int LIS(vector<int>& arr) {if (arr.empty())return 0;// write code hereint N = arr.size();vector<int>dp(N, 1);//每个位置最长递增子序列的长度至少为1自己本身就是//dp的含义是必须以i位置结尾的情况下最长递增子序列的最大长度int maxLen = 1;for (int i = 1; i < N; i++) {for (int j = 0; j < i; j++) {if (arr[i] > arr[j]) {dp[i] = max(dp[i], dp[j] + 1); //长度加1}}maxLen = max(maxLen, dp[i]);//更新最大长度}return maxLen;}};

二.最长递增子序列问题II

1.对应牛客网链接:

最长上升子序列(二)_牛客题霸_牛客网 (nowcoder.com)

2.题目描述:

 3.解题思路:

1.在这里我们引入end数组,end[i]的值为最目前为止长度为i+1的最小结尾

2.每次去end数组里面去找大于等于arr[i]最左的位置

 

我们看同样是长度为2的子序列,[2,3]就比[2,5]好。因为[2,3]后面如果有4的话,组成[2,3,4]长度就是3了,但是[2,5]因为不满足条件,就没法组队了。

我们组成子序列的时候,不仅要让这个序列尽可能的长,而且要让子序列中的上升的时候尽可能的缓慢,[2,3]就比[2,5]上升的缓慢,这样就有机会能拼接出更长的上升子序列。我们用一个数组来保存当前的最长上升子序列,这个数组是严格递增的。
因为是严格递增的,数组中最后一个值nums[max]就是最大值,如果下次再碰到一个数字n,它比num[max]还要大,那么很明显,这个子序列的长度就要+1,并且将数组n添加到数组的末尾。

[2,3,7,8,11,13,18]是目前为止最长的上升子序列,之后如果又碰到了19,或者101,因为他们都大于数组中的最大值18,所以直接将其添加到数组末尾就可以了,同时子序列的长度要+1。19和101的例子很好理解,但如果下次碰到的数字是6或者12呢?因为要让子序列上升的尽可能缓慢,那么让[2,5,7...]变成[2,5,6...]更合适,因为后者上升的更缓慢。同样,将[...8,11,13,18]变成[...8,11,12,18]也是上升的更缓慢一点。
也就是,已知上升子序列[i,i_1,i_2,....,i_n],现在我们在继续遍历的过程中碰到了一个值i_k,这个值是小于i_n的,所以上升子序列的长度还是不变。但是我们需要找到一个位置,将i_k替换掉某个旧的值。

对应动图:

4.对应代码:

class Solution {public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** 该数组最长严格上升子序列的长度* @param a int整型vector 给定的数组* @return int整型*/int LIS(vector<int>& arr) {// write code hereif (arr.empty()) {return 0;}int N = arr.size();vector<int>end(N);//end[i]的含义是目前为止长度为i+1的最小结尾end[0] = arr[0];int L = 0;int maxLen = 1;int right = 0; //用于控制end数组的范围int R = right;for (int i = 1; i < N; i++) {L = 0;R = right;while (L <= R) {//用于查找大于等于arr[i]最左边的位置int mid = (L + R) >> 1;if (arr[i] > end[mid]) {L = mid + 1;} else {R = mid - 1;}}right = max(right, L); //更新右边界maxLen = max(maxLen, L + 1);end[L] = arr[i];}return maxLen;}
};

三. 最长递增子序列问题III

1.对应letecode链接:

最长上升子序列(三)_牛客题霸_牛客网 (nowcoder.com)

2.题目描述:

3.解题思路

1.本题只是上题的一个升级版我们只需要定义一个变量记录 一下最长递增子序列的结尾位置在哪里即可,然后再依次遍历

4.对应代码:

class Solution {public:/*** retrun the longest increasing subsequence* @param arr int整型vector the array* @return int整型vector*/vector<int> LIS(vector<int>& arr) {// write code hereif (arr.empty()) {return {};}int N = arr.size();vector<int>dp(N, 1);vector<int>end(N);int maxLen = 1;int maxIndex = 0;end[0] = arr[0];int right = 0;int L = 0;int R = right;for (int i = 1; i < N; i++) {L = 0;R = right;while (L <= R) {int mid = (L + R) >> 1;if (arr[i] > end[mid]) {L = mid + 1;} else {R = mid - 1;}}right = max(right, L);maxLen = max(maxLen, L + 1);end[L] = arr[i];dp[i] = L + 1;if (dp[i] >= maxLen) {//由于要求子典序最小maxIndex = i;maxLen = dp[i];}}vector<int>ans(maxLen);//获取最长的递增子序列for (int i = maxIndex; i >= 0; i--) {if (dp[i] == maxLen) {ans[--maxLen] = arr[i];}}return ans;}
};

思考题:如果要获取所有递增子序列了?

#include<iostream>
#include<vector>
using namespace std;
vector<int> process(vector<int>& arr,vector<int>&dp ,int maxLen, int index) {//获取所有最长递增子序列vector<int>ans(maxLen);for (int i = index; i >= 0; i--) {if (dp[i] == maxLen) {ans[--maxLen] = arr[i];}}cout << "进来" << endl;return ans;}
int main() {int N;cin >> N;vector<int>arr(N);for (int i = 0; i < N; i++) {cin >> arr[i];}vector<int>dp(N, 1);vector<int>end(N);int maxLen = 1;int maxIndex = 0;end[0] = arr[0];int right = 0;int L = 0;int R = right;for (int i = 1; i < N; i++) {L = 0;R = right;while (L <= R) {int mid = (L + R) >> 1;if (arr[i] > end[mid]) {L = mid + 1;}else {R = mid - 1;}}right = max(right, L);maxLen = max(maxLen, L + 1);end[L] = arr[i];dp[i] = L + 1;if (dp[i] >= maxLen) {maxIndex = i;maxLen = dp[i];}}vector<vector<int>>ans;for (int i = 0; i < N; i++) {if (dp[i] == maxLen) {ans.push_back(process(arr, dp, maxLen, i));}}for (int i = 0; i < ans.size(); i++) {for (int j = 0; j < ans[0].size(); j++) {cout << ans[i][j] << " ";}cout << endl;}return 0;
}


http://chatgpt.dhexx.cn/article/XBjlMRXK.shtml

相关文章

UDP协议详细解析

一、基本概念 基本定义&#xff1a;UDP 是User Datagram Protocol的简称&#xff0c; 中文名是用户数据报协议&#xff0c;是OSI&#xff08;Open System Interconnection&#xff0c;开放式系统互联&#xff09; 参考模型中一种无连接的传输层协议&#xff0c;提供面向事务的…

tcp read 和 udp recvfrom

udp中写一个长度为0的数据报是可行的&#xff0c;这导致一个包含IP头部、udp头部和没有数据的IP数据报。这也意味着对于数据报协议&#xff0c;recvfrom返回0值也是可行的&#xff1a;它不表示对方已经关闭了连接&#xff0c;这与tcp套接口上read返回0值的情况不同。由于udp是无…

UDPTCP

目录 Socket 一.UDP 特点 基于UDP实现回显服务器 服务器 客户端 端口冲突 图解 二.TCP 特点 基于TCP实现回显服务器 服务器 客户端 图解 Socket Socket套接字&#xff0c;是由系统提供用于网络通讯的技术&#xff0c;是基于TCP/IP协议的网络通信的基本操作单元&#xff0c;基于…

Reliable UDP

Reliable UDP&#xff08;可靠的UDP&#xff09;是一套服务品质的增强&#xff0c;比如拥挤控制调整&#xff0c;数据重传&#xff0c;薄化服务器算法等&#xff0c;这些增强可以提高服务器在数据包丢失和网络拥挤的条件下向RTP客户表现品质良好的RTP流的能力。Reliable UDP’的…

TCP /UDP

TCP与UDP工作在传输层&#xff0c;在程序之间传数据&#xff08;视频&#xff0c;聊天&#xff0c;图片&#xff0c;网页&#xff09; TCP基于连接的&#xff0c;可靠的&#xff08;及时知对方接受/拒绝&#xff0c;是否传错&#xff09;&#xff08;文本&#xff0c;网页&…

UDP、TCP

传输层协议UDP、TCP 一、TCP/UDP的任务二、UDP1.UDP概述2.UDP报文格式3.使用UDP的应用层协议 三、TCP1.TCP概述2.TCP报文3.TCP三次握手4.四次挥手5.超时重传6.流量控制和快重传7.拥塞控制8.延迟应答、捎带应答9.粘包问题10.基于TCP的应用层协议 四、总结 一、TCP/UDP的任务 我们…

tcp udp proxy

服务目的 首先如下图所示&#xff1a; 作为一个内外网的通信&#xff0c;必须使用tcp 和 udp 的proxy 把内网和外网打通&#xff0c;比如中间是一个有两个网卡的路由器&#xff0c;打通以后&#xff0c;由proxy 发送数据到服务端&#xff0c;服务端按照上图处于外网。 服务端…

UDP-RTP协议解析

一、RTP协议 数据传输协议RTP&#xff0c;用于实时传输数据。RTP报文由两部分组成&#xff1a;报头和有效载荷 二、RTP的会话过程 当应用程序建立一个RTP会话时&#xff0c;应用程序将确定一对目的传输地址。目的传输地址由一个网络地址和一对端口组成&#xff0c;有两个端口&a…

UDP 理解

这里需要指出的一点是&#xff0c;伪首部完全是虚拟的&#xff0c;它并不会和用户数据报一起被发送出去&#xff0c;只是在校验和的计算过程中会被使用到&#xff0c;伪首部主要来自于运载UDP报文的IP数据报首部&#xff0c;将源IP地址和目的IP地址加入到校验和的计算中可以验证…

关于TCP/UDP

目录 1、TCP协议 1.1 TCP协议格式 1.2 TCP协议原理 2、UDP协议 在学习TCP/UDP之前先来了解以下整体的通信传输&#xff0c;它是一个向下封装、向上分用的过程&#xff1a; 这是TCP/IP四层模型&#xff0c;所以要想实现通讯&#xff0c;通过TCP建立和断开连接是至关重要的&a…

UDP详解

1、UDP数据包格式 UDP 是User Datagram Protocol的简称&#xff0c; 中文名是用户数据报协议&#xff0c;是OSI&#xff08;Open System Interconnection&#xff0c;开放式系统互联&#xff09; 参考模型中一种无连接的传输层协议&#xff0c;提供面向事务的简单不可靠信息传…

TCPUDP相关介绍

TCP and UDP TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是面向连接的协议&#xff0c;也就是说&#xff0c;在收发数据前&#xff0c;必须和对方建立可靠的连接。 一个TCP连接必须要经过三次握手才能建立起来。断开连接需要四次挥手才…

TCPUDP

TCP&#xff1a;面向连接的服务&#xff0c;可靠的进程到进程的通信协议。&#xff08;因为TCP里面封装了端口号&#xff0c;端口号就意味着一个服务&#xff0c;进程&#xff09;&#xff1b;应用场景&#xff1a;如&#xff1a;文件传输&#xff1b;HTTP应用层协议 UDP&…

TCP/UDP

Tcp / ip : 应用层、传输层、网络层、网络接口层 查看本机ip&#xff1a; windons r &#xff08;进入交互换环境&#xff09;ipconfigping 本机ip 查看本机网络有无问题 端口&#xff1a; 知名端口(固定端口)&#xff1a;0—1023动态端口&#xff1a;程序可以设置的端口 1…

UDP协议的详细解析

UDP数据报 一、UDP的概述&#xff08;User Datagram Protocol&#xff0c;用户数据报协议&#xff09; UDP是传输层的协议&#xff0c;功能即为在IP的数据报服务之上增加了最基本的服务&#xff1a;复用和分用以及差错检测。 UDP提供不可靠服务&#xff0c;具有TCP所没有的优…

UDP协议详解

一、UDP协议概述 传输层另一个重要的协议就是用户数据报协议 UDP。UDP 只在 IP 的数据报服务之上增加了很少一点的功能&#xff0c;这就是复用和分用的功能以及差错检测的功能。 <注> UDP(User Datagram Protocol&#xff0c;用户数据报协议) UDP的主要特点是&#xff1a…

截图文字识别工具

tkinter程序源码&#xff1a;初识Python&#xff0c;如有不足请多指教。 import tkinter as tk import keyboard # 安装&#xff1a; pip install keyboard from PIL import ImageGrab # pip install pillow import time from aip import AipOcr # pip install baidu-a…

电脑截图如何快速识别文字?3分钟教会你快速截图识别怎么做

电脑截图已经成为我们日常生活中的常见操作&#xff0c;无论是工作还是学习&#xff0c;我们都有可能需要截取电脑屏幕上的某个区域进行保存或分享。但是&#xff0c;有时候我们需要识别截图中的文字内容&#xff0c;这时候该怎么办呢&#xff1f;接下来&#xff0c;本文将为大…

python截图识别文字_10几行代码,用python打造实时截图识别OCR|python基础教程|python入门|python教程...

https://www.xin3721.com/eschool/pythonxin3721/ 你一定用过那种“OCR神器”&#xff0c;可以把图片中的文字提取出来&#xff0c;极大的提高工作效率。 &#xff01; 今天&#xff0c;我们就来做一款实时截图识别的小工具。顾名思义&#xff0c;运行程序时&#xff0c;可以…

chrome拓展 --截屏文字识别

文章目录 场景源代码功能实现点击在页面上出现裁剪框百度云文字识别复制选中 参考 场景 因为学习通题目都加密了复制过来也无法进行搜题 无奈写了这个插件 为什么使用插件的形式 而不是脚本 &#xff1f; 使用了html2canvas结果是比的是dom文字变成了加密过的 无法识别 于是使用…