【C++单调队列】1438. 绝对差不超过限制的最长连续子数组|1672

news/2024/9/30 10:34:10 标签: c++, 算法, 力扣, 单调队列, 最长, 子数组, 绝对差

本文时间知识点

C++队列、双向队列

LeetCode1438. 绝对差不超过限制的最长连续子数组

给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit 。
如果不存在满足条件的子数组,则返回 0 。
示例 1:
输入:nums = [8,2,4,7], limit = 4
输出:2
解释:所有子数组如下:
[8] 最大绝对差 |8-8| = 0 <= 4.
[8,2] 最大绝对差 |8-2| = 6 > 4.
[8,2,4] 最大绝对差 |8-2| = 6 > 4.
[8,2,4,7] 最大绝对差 |8-2| = 6 > 4.
[2] 最大绝对差 |2-2| = 0 <= 4.
[2,4] 最大绝对差 |2-4| = 2 <= 4.
[2,4,7] 最大绝对差 |2-7| = 5 > 4.
[4] 最大绝对差 |4-4| = 0 <= 4.
[4,7] 最大绝对差 |4-7| = 3 <= 4.
[7] 最大绝对差 |7-7| = 0 <= 4.
因此,满足题意的最长子数组的长度为 2 。
示例 2:
输入:nums = [10,1,2,4,7,2], limit = 5
输出:4
解释:满足题意的最长子数组是 [2,4,7,2],其最大绝对差 |2-7| = 5 <= 5 。
示例 3:
输入:nums = [4,2,2,2,4,4,2,2], limit = 0
输出:3
提示:
1 <= nums.length <= 105
1 <= nums[i] <= 109
0 <= limit <= 109

滑动窗口(错误解法)

i从小到大枚举nums[i],令nums[i1…i]是符合条件的子数组
由于abs(i1-1,nums[i])>limit,故nums[i1-1…i1+1]一定不符合条件,故从i1可以判断。
如果nums[i1]和nums[i+1]符合条件,则i1++。
错误原因:nums[i1+2]可以和nums[i]不符合

滑动窗口+有序映射(集合)

记录nums[i1…i]的值和下标。如果set最小的值和nums[i]超过限制,则将下标小于等于最小值下标的删除。set最大值超限,也是如此。处理完超限后,将nums[i]放到set。此时的set.size就是以 nusm[i]结尾的最长子数组长度。
时间复杂度:O(nlogn)

滑动窗口+单调队列

两个双向队列分别记录(nums[i],i) ,其中i ∈ \in [0,j-1]。
minQue如果有元素x,其下标为i1 ,符合小于x <nums[i]- limit,则删除下标小于等于i1的元素。
i1 <i2,且nums[i1]>= nums[i2] 。如果i1符合条件,则i2也一定符合。而i2符合会删除i1。故i1可以省略,或者说i1被i2淘汰后。
淘汰后,从队首到队尾,严格升序,即最小元素在队首。
maxQue类似,严格降序。
队首可能有多个元素超限,一个队列超限后,要清理另一个队列的下标。
时间复杂度:O(n)

代码

核心代码

class Solution {
		public:
			int longestSubarray(vector<int>& nums, int limit) {
				deque<int> minQue, maxQue;
				int ans = 0;
				int del = -1;
				for (int i = 0; i < nums.size(); i++) {					
					while (minQue.size() && (nums[minQue.front()] < nums[i] - limit )) {
						del = max(del, minQue.front());
						minQue.pop_front();
					}
					while (maxQue.size() && (nums[maxQue.front()] > nums[i] + limit)) {
						del = max(del, maxQue.front());
						maxQue.pop_front();
					}
					while (minQue.size() && (minQue.front() <= del)) { minQue.pop_front(); }
					while (maxQue.size() && (maxQue.front() <= del)) { maxQue.pop_front(); }					
					while (minQue.size() && (nums[minQue.back()] >= nums[i])) {
						minQue.pop_back();
					}
					while (maxQue.size() && (nums[maxQue.back()] <= nums[i])) {
						maxQue.pop_back();
					}
					minQue.emplace_back(i);
					maxQue.emplace_back(i);
					ans = max(ans, i - del);
				}
				return ans;
			}
		};

单元测试

	vector<int> nums;
		int limit;
		TEST_METHOD(TestMethod1)
		{
			nums = {1,5 }, limit = 3;
			auto res = Solution().longestSubarray(nums, limit);
			AssertEx(1, res);
		}
		TEST_METHOD(TestMethod2)
		{
			nums = { 1,5 }, limit = 5;
			auto res = Solution().longestSubarray(nums, limit);
			AssertEx(2, res);
		}
		TEST_METHOD(TestMethod11)
		{
			nums = { 8, 2, 4, 7 }, limit = 4;
			auto res = Solution().longestSubarray(nums, limit);
			AssertEx(2, res);
		}
		TEST_METHOD(TestMethod12)
		{
			nums = { 10,1,2,4,7,2 }, limit = 5;
			auto res = Solution().longestSubarray(nums, limit);
			AssertEx(4, res);
		}
		TEST_METHOD(TestMethod13)
		{
			nums = { 4,2,2,2,4,4,2,2 }, limit = 0;
			auto res = Solution().longestSubarray(nums, limit);
			AssertEx(3, res);
		}
		TEST_METHOD(TestMethod14)
		{
			nums = { 2,2,2,4,4,2,5,5,5,5,5,2 }, limit = 2;
			auto res = Solution().longestSubarray(nums, limit);
			AssertEx(6, res);
		}
		TEST_METHOD(TestMethod15)
		{
			nums = { 24,12,71,33,5,87,10,11,3,58,2,97,97,36,32,35,15,80,24,45,38,9,22,21,33,68,22,85,35,83,92,38,59,90,42,64,61,15,4,40,50,44,54,25,34,14,33,94,66,27,78,56,3,29,3,51,19,5,93,21,58,91,65,87,55,70,29,81,89,67,58,29,68,84,4,51,87,74,42,85,81,55,8,95,39 }, limit = 87;
			auto res = Solution().longestSubarray(nums, limit);
			AssertEx(25, res);
		}
		TEST_METHOD(TestMethod16)
		{
			nums = { 7,40,10,10,40,39,96,21,54,73,33,17,2,72,5,76,28,73,59,22,100,91,80,66,5,49,26,45,13,27,74,87,56,76,25,64,14,86,50,38,65,64,3,42,79,52,37,3,21,26,42,73,18,44,55,28,35,87 }, limit = 63;
			auto res = Solution().longestSubarray(nums, limit);
			AssertEx(9, res);
		}

扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。


http://www.niftyadmin.cn/n/5684909.html

相关文章

Linux中安装ffmpeg

Linux中安装ffmpeg 一、下载二、安装三、测试 一、下载 先到这里下载ffmpeg。 二、安装 先将上传到服务器的某一目录&#xff0c;我这里是&#xff1a; /usr/local/ffmpeg 然后解压&#xff0c;解压命令如下&#xff1a; tar -xvf “你的安装包名称”我的是&#xff1a; ta…

二叉搜索树(c++版)

前言 在前面我们介绍过二叉树这个数据结构&#xff0c;今天我们更进一步来介绍二叉树的一种在实现中运用的场景——二叉搜索树。二叉搜索树顾名思义其在“搜索”这个场景下有不俗的表现&#xff0c;之所以会这样是因为它在二叉树的基础上添加了一些属性。下面我们就来简单的介…

矩阵奇异值

一、ATA 任给一个矩阵A&#xff0c;都有&#xff1a; ATA 为一个对称矩阵 例子&#xff1a;A为一个mn的矩阵&#xff0c;A的转置为一个nm的矩阵 对称矩阵的重要性质如下&#xff1a; ① 对称矩阵的特征值全为实数&#xff08;实数特征根&#xff09; ② 任意一个n阶对称矩阵…

ubuntu切换源方式记录(清华源、中科大源、阿里源)

文章目录 前言一、中科大源二、清华源三、阿里源 前言 记录ubunut切换各个源的方式。 备注&#xff1a;更换源之后使用sudo apt-get update更新索引。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、中科大源 地址&#xff1a;https://mirrors.u…

RK3588主板PCB设计学习(一)

DCDC电路可以直接参考数据手册&#xff1a; 电源输出3A&#xff0c;回流GND也应该是3A&#xff0c;回流路径和输出路径的电流是一致的&#xff0c;不要输出路径布线很粗&#xff0c;GND回流路径很细&#xff0c;并且应该保证回流面积最小&#xff1a; 这一点讲的很到位&#xf…

第十四周学习周报

目录 摘要Abstract1. LSTM的代码实现2. 序列到序列模型3. 梯度与方向导数总结 摘要 在上周的学习基础之上&#xff0c;本周学习的内容有LSTM的代码实现&#xff0c;通过对代码的学习进一步加深了对LSTM的理解。为了切入到transformer的学习&#xff0c;本文通过对一些应用例子…

SQL中基本SELECT语句及常见关键字的使用(内连接,左/右连接)

这里写目录标题 SQL中基本SELECT语句的使用SQL语法简介DDL、DML、DCLSEECT SELECT常用关键词group by分组having筛选limit限定条数UION和UION ALL合并SQL执行顺序 联表查询多表查询示例特殊用法&#xff1a;笛卡尔积&#xff08;交叉连接&#xff09;等值连接vs非等值连接自连接…

Visual Studio-X64汇编编写

纯64位汇编&#xff1a; includelib ucrt.lib includelib legacy_stdio_definitions.lib includelib user32.libextern printf:proc extern MessageBoxA:proc.data szFormat db "%s",0 szHello db "HelloWorld",0 szRk db "123",0.code start p…