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

article/2025/9/21 0:22:16

定义

最长上升子序列(Longest Increasing Subsequence,LIS),在计算机科学上是指一个序列中最长的单调递增的子序列。

问题描述

给定一个长度为 N 的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱)。例如:给定一个长度为 5 的数组{5, 6, 1, 2, 8},则其最长的单调递增子序列为 {5,6,8},长度为 3。

解法

动态规划

时间复杂度

该方法的时间复杂度为 O(n^{2})

实现过程

下面我们用一个实例来分析一下动态规划求解 LIS 的整个过程。假设数组 A 的内容为 {5, 6, 1, 2, 8}。

1、第一个元素直接设置 LIS 长度为 1 即可。如下图所示。

2、第二个元素 6 大于前面所有元素进行比较。5<6,则 LIS[1] = LIS[0]+1 = 2。如下图所示。

3、第三个元素 1 和前面的所有元素进行比较。1<6,则 LIS 的长度可能为 1;1<5,则 LIS 的长度可能为 1;取最大值,LIS[2]=1 。如下图所示。

4、第四个元素 2 和前面的所有元素进行比较。1<2,则 LIS 的长度可能为 LIS[2]+1 = 2;6>2,则 LIS 的长度可能为 1;5>2,则 LIS 的长度可能为 1;取最大值,LIS[3]=2 。如下图所示。

5、第五个元素 8 和前面的所有元素进行比较。2<8,则 LIS 的长度可能为 LIS[3]+1 = 3;8>1,则 LIS 的长度可能为 LIS[2]+1 = 2;8>6,则 LIS 的长度可能为 LIS[1]+1 = 3;8>5,则 LIS 的长度可能为 LIS[0]+1 = 2;取最大值,LIS[4]=3 。如下图所示。

算法思路

设长度为 N 的数组为 {a0,a1, a2, ..., an-1),则假定以 aj 结尾的数组序列的最长递增子序列长度为 LIS(j),则 LIS(j) = {max(LIS(i))+1, i<j 且 a[i] < a[j] }。

二分查找

时间复杂度

该方法的时间复杂度为 O(n*logn)

算法描述

我们可以引入一个新数组 maxV,该数组的特性为:

长度为 1 的递增子序列最大元素的最小值为 maxV[1];

长度为 2 的递增子序列最大元素的最小值为 maxV[2];

长度为 LIS[i] 的递增子序列最大元素的最小值为 maxV[LIS[i]]。

首先,证明 maxV[] 是递增的,因此可以使用二分搜索。我们可以用数学归纳法即可证明:若前 k 个元素是递增的,一定有 maxV[k+1] \geq maxV[k]

证明:假设不成立,则 maxV[k+1] < maxV[k]。

根据 maxV[k+1] 的定义,存在一个长度是 k+1 的 LIS,并且以 maxV[k+1] 为最大元素。将上述子序列去掉最后一个元素maxV[k+1], 得到长度为 k,且最大元素 < maxV[k+1] < maxV[k]。

这显然与 maxV[k] 的定义矛盾。所以假设不成立。

实现过程

我们用一个实例来分析一下二分查找求解 LIS 的整个过程。假设数组 A 的内容为 {5, 6, 1, 2, 8}。

我们用 LIS[i-1] 表示长度为 i 的最长递增子序列末尾的数据。

1、第一个元素直接加入到 LIS 数组中。LIS[0]=5,表示长度为 1 的 LIS 数组最后一个元素是 5。如下图所示。

2、第二个元素为 6,因为 6>LIS[0],构成递增,将数字 6 加入到 LIS 数组中,即 LIS[1]=6,表示长度为 2 的 LIS 数组的末尾是 6。如下图所示。

3、第三个元素为 1,1<LIS[2],因此前面一定有一个位置的数据可以换成 1,并且后面的递增性质不会被破坏。因此我们使用二分查找在 LIS 数组中找到 1 的位置,我们知道 lower_bound 查找的位置为 0。也就是说 LIS[0] 可以被替换为 1。如下图所示。

4、第四个元素为 2,2<LIS[2],因此前面一定有一个位置的数据可以换成 2,并且后面的递增性质不会被破坏。因此我们使用二分查找在 LIS 数组中找到 2 的位置,我们知道 lower_bound 查找的位置为 1。也就是说 LIS[1] 可以被替换为 2。如下图所示。

4、第五个元素为 8,8>LIS[2],构成递增,将数字 8 加入到 LIS 数组中,即 LIS[2]=8,表示长度为 3 的 LIS 数组的末尾是 8。如下图所示。

这样,我们完成了遍历,这时候我们可以发现 LIS 数组的小标为 2,表示我们要求解的 LIS 长度为 3。

算法思路

将 array[i] 在当前的 maxV[] 数组中进行二分搜索,找到位置 k,maxV[k] < array[i] < maxV[k+1]。

将 array[i] 加入 maxV[] 数组。仅仅影响 maxV[k+1]  (maxV[k+1] = array[i]),而对其他的元素不产生影响。

参考实现

int LIS(int *a, int n) {if (n<=0) {return 0;}vector<int> maxV;maxV.push_back(a[0]);for(int i=1; i<n; ++i) {if (a[i] > *maxV.rbegin()) {maxV.push_back(a[i]);} else {*lower_bound(maxV.begin(), maxV.end(), a[i]) = a[i];} }return maxV.size();
}

 


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

相关文章

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

目录 一.最长递增子序列问题I 二.最长递增子序列问题II 三. 最长递增子序列问题III 一.最长递增子序列问题I 1.对应牛客网链接 最长上升子序列(一)_牛客题霸_牛客网 (nowcoder.com) 2.题目描述&#xff1a; 3.解题思路 1.首先我们分析题意&#xff1a;最长递增子序列拆&#x…

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;可以…