【题目/算法训练】:单调队列单调栈

news2024/9/23 19:26:14

🚀 前言:

【算法】单调队列&&单调栈 可以在看完这篇文章后,再来写下面的题目

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

思路:

      1) 就相当于滑动窗口,维护滑动窗口内的两个值,一个是最大值,一个是最小值,如果当前滑动窗口的最大值和最小值的差值都不超过  limit ,说明滑动窗口内任意两个数的差值都不会超过  limit 

       2)由于需要维护两个值 ,因此我们需要两个单调队列,同时维护一个区间的值,一个去维护最大值,一个去维护最小值

       3) 由于要求最长连续子数组的长度,那么我们假设已经 有【l,r - 1】满足条件的最长子数组长度,然后尾指针向后移动一位,假设此时【l,r】的最大差值已经超过 limit,此时 应该向后移动,,这道题本质就是一个变长的滑动窗口,其长度是根据题目所给条件来进行调整。

class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        //处理边界情况
        if (limit < 0) return 0;
      
        deque<int> min_q, max_q;
        int l = 0, ans = 1 ;
        min_q.push_back(0);
        max_q.push_back(0);

        for (int r = 1, n = nums.size(); r < n; r++) {
            while (!min_q.empty() && nums[r] < nums[min_q.back()]) min_q.pop_back();
            while (!max_q.empty() && nums[r] > nums[max_q.back()]) max_q.pop_back();
            min_q.push_back(r);
            max_q.push_back(r);

            if (nums[max_q.front()] - nums[min_q.front()] > limit) {
                if (min_q.front() == l) min_q.pop_front();
                if (max_q.front() == l) max_q.pop_front();
                l++;
            }
            ans = max(ans, r - l + 1);
        }
        return ans;
    }
};

二、最大矩形面积

思路:

 1) 假设我们现在可以切割出的最大矩形面积为S;

 2)此时矩形高度等于其范围内最矮木板的高度。

 3)假设最大矩形两边各有1号和2号两块木板,此时1和2号的高度比矩形高度要小,

 4) 以每一块木板作为矩形最大高度的基准值,然后枚举去判断能够可以切出来的最大面积。因此我们需要求该木板左右两边最近的1,2号木板,就可以用单调栈。

#include<iostream>
#include <vector>
#include <cstdio>
#include <stack>
#include <algorithm>
#include <cstring>
using namespace std;

typedef long long ll;

int main()
{
	int n;
	cin >> n;
	vector<ll> arr(n + 2, -1);  //让最左边和最右边木板旁边还有木板
	vector<ll> l(n + 2), r(n + 2);//分别存储左右两边小于第i块木板的那个下标
	for (int i = 1; i <= n; i++) cin >> arr[i];
	
	stack<ll>s;
	for (int i = 1; i <= n + 1; i++) {
		while (!s.empty() && arr[i] < arr[s.top()]) {
			r[s.top()] = i;
			s.pop();
		}
		s.push(i);
	}
	while (!s.empty()) s.pop();
	for (int i = n; i >= 0; i--) {
		while (!s.empty() && arr[i] < arr[s.top()]) {
			l[s.top()] = i;
			s.pop();
		}
		s.push(i);
	}
	ll ans = 0;
	for (int i = 1; i <= n; i++) { //以每一块木板为基准值切出的最大面积
		ll height = arr[i], width = r[i] - l[i] - 1;
		ans = max(ans, height * width);
	}
	cout << ans << "\n";
	return 0;
}

三、接雨水

首先由题目可知只有凹形才能接雨水,因此我们假设已经存在1号柱子到2号柱子如下构成的绿色接雨水面积,当再来了一个3号柱子,我们又可以新接一些雨水,即黄色面积,假设1号柱子的下标为i,3号柱子的下标为j,此时黄色部分的长度为 j - i,高度为min (h3 - h1) -h2

因此我们不断往后增加柱子,比如4号柱子,那里又可以增加红色雨水面积,加入5号柱子,计算不出我们可以接雨水的面积,再增加6号(仍然没有新增雨水的量),再加入7号柱子,

此时h7和h5可以算出可以接雨水的量,此时可以当作h6不存在,如下图所示

因此可知我们应该需要维护的就是上图中h4、h5、h7这种单调递减的序列,然后每次在后面增加一个柱子,如果我们增加的柱子比我们最后的柱子要高,就可以形成新的雨水,然后计算增加雨水的量,进行累加即可,易知应该需要用到单调栈

class Solution {
public:
    int trap(vector<int>& height) {
        stack<int> s;
        int ans = 0;
        for (int i = 0; i < height.size(); i++) {
            while (!s.empty() && height[s.top()] < height[i])
            {
                int min_h = height[s.top()];//记录弹出柱子的高度
                s.pop();
                if (s.empty()) break;
        //计算出弹出柱子两侧相邻最矮柱子的高度与弹出柱子高度差,再乘以下标差,此时就为新增雨水面积
                ans = ans + (min(height[s.top()], height[i]) - min_h) * (i - s.top() - 1); 
            }
            s.push(i);
        }
        return ans;
    }
};

四、和至少为K的最短子数组

思路:

       假设如下每个节点都代表了前缀和数组中的每一个值,假设当前已经遍历到黄色这个节点,绿色代表黄色点之前所有点的最小值,红色点代表从绿色到黄色点区间内的最小值,蓝色点则代表红色点到黄色点区间内的最小值

       此时我们需要找到黄色点前的一个点,使得黄色点需要减去那一个值,并且这个差值必须大于等于K,因此我们需要找的就是黄色点前的最小值,假如黄色点减去绿色点的差值大于等于K,但是由于我们要求最短子数组,此时绿色点就可以被抛弃,即弹出,因此我们就需要在绿色点后面找点,即红色点,如果黄色点与红色点的差值也大于等于K,那么黄色点也弹出,那我们就去找蓝色点,不断往后,即需要维护绿红蓝这三个点

        易知应该使用单调队列来解决该题,即把原数组处理为前缀和数组,然后将原数组中每一项依次性压入到单调队列中,每次压入前,需要用当前的值和单调队列的队首进行比较,若当前值减去队首元素的值大于等于K,此时队首元素就可以出队,然后再把当前元素压入单调队列

class Solution {
public:
    int shortestSubarray(vector<int>& nums, int k) {
        int n = nums.size();
        vector<long long> s(n + 1, 0);//前缀和数组
        for (int i = 1; i <= n; i++) {
            s[i] = s[i - 1] + nums[i - 1];
        }
        deque<int>q;
        q.push_back(0);
        int ans = n + 1;
        for (int i = 1; i <= n; i++) {
            while (!q.empty() && s[i] - s[q.front()] >= k) {
                ans = min(ans, i - q.front());
                q.pop_front();
            }

            while (!q.empty() && s[i] < s[q.back()]) q.pop_back();
            q.push_back(i);
        }

        if (ans == n + 1) return -1;
        return ans;
    }
};

五、双生序列

思路:

       假设已有A、B两序列,两个都固定了结尾位置r的情况下,它们的趋势相同就是从最小值到最小值后面的最小值到最小值后面的最小值的最小值的所在位置相同,然后将黄蓝绿红的位置存储在单调队列中,其趋势相同也意味着它们在单调队列所存储的元素也相同,注意在单调队列中所存储位置对应值应该是单调递增的

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <deque>
using namespace std;

int main()
{
	int n;
	cin >> n;
	vector<int> a(n + 1), b(n + 1);
	for (int i = 1; i <= n; i++) cin >> a[i];
	for (int i = 1; i <= n; i++) cin >> b[i];
	deque<int> ap, bp;
	int p; //找最大值i
	for (p = 1; p <= n; p++)
	{
		while (!ap.empty() && a[p] <= ap.back()) ap.pop_back();
		while (!bp.empty() && b[p] <= bp.back()) bp.pop_back();

		ap.push_back(a[p]);
		bp.push_back(b[p]);

		if (ap.size() != bp.size()) break; //说明到此位置结束
	}

	cout << p - 1<< endl; 
	return 0;
}

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

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

相关文章

溶解氧(DO)理论指南(3)

转载自梅特勒官网资料&#xff0c;仅用于学习交流&#xff0c;侵权则删&#xff01; 溶解氧理论指南 设备操作3.1 DO电极准备3.2 DO电极校准3.3 进行DO测量3.4 转换单位3.5 维护和储存 设备操作 本章总结了 DO电极日常使用的一些建议。它们基于普遍接受的操作规则。 3.1 DO电…

【数据结构——链表的深度探索】从实现到应用,保姆级攻略

【数据结构——链表深度探索】从实现到应用&#xff0c;保姆级攻略 &#x1f341;1. 链表的介绍&#x1f341;2. 链表的实现&#x1f341;2.1 单向链表&#x1f341;2.1.1 size()&#x1f341;2.1.2 display()&#x1f341;2.1.3 contains(int key)&#x1f341;2.1.4 addFirst…

本地部署,强大的面部修复与增强网络CodeFormer

目录 什么是 CodeFormer&#xff1f; 技术原理 主要功能 应用场景 本地部署 运行结果 结语 Tip&#xff1a; 在图像处理和计算机视觉领域&#xff0c;面部修复和增强一直是一个备受关注的研究方向。近年来&#xff0c;深度学习技术的飞速发展为这一领域带来了诸多突破性…

C++ 语法习题(3)

字符串 1.字符串长度 给定一行长度不超过 100 的非空字符串&#xff0c;请你求出它的具体长度。 输入格式 输入一行&#xff0c;表示一个字符串。注意字符串中可能包含空格。 输出格式 输出一个整数&#xff0c;表示它的长度。 数据范围 1≤字符串长度≤100 字符串末尾…

2024学生党蓝牙耳机什么牌子好?品牌高性价比蓝牙耳机推荐

2024年&#xff0c;对于追求性价比和品质的学生党来说&#xff0c;选择一款合适的蓝牙耳机是提升学习和生活品质的重要一环。面对市场上琳琅满目的蓝牙耳机产品&#xff0c;2024学生党蓝牙耳机什么牌子好&#xff1f;如何找到既满足音质需求又具备高性价比的款式呢&#xff1f;…

Odoo免费开源ERP如何处理汽车零部件企业的OE编码问题

业务背景 汽车零部件企业在每个汽配零件都有OE编号&#xff0c;即原厂编号&#xff0c;Original Equipment Number。一个配件&#xff0c;可能可以在多个车型上使用&#xff0c;对应的&#xff0c;就有多个可兼容的OE编号。 客户下单时候&#xff0c;直接报OE编号&#xff0c…

MT3054 搭积木

1.思路&#xff1a; 把二维矩阵转化成一维编号&#xff0c;之后将编号使用并查集&#xff0c;看最后是否在同一个集合中即可。 2.代码&#xff1a; #include <bits/stdc.h> using namespace std; const int N 1e3 10; int n, m, cnt, root; int fa[N * N]; int dx[…

[机器学习]-人工智能对程序员的深远影响——案例分析

机器学习和人工智能对未来程序员的深远影响 目录 机器学习和人工智能对未来程序员的深远影响1. **自动化编码任务**1.1 代码生成1.2 自动调试1.3 测试自动化 2. **提升开发效率**2.1 智能建议2.2 项目管理 3. **改变编程范式**3.1 数据驱动开发 4. **职业发展的新机遇**4.1 AI工…

【代码随想录】【算法训练营】【第63天】 [卡码53]寻宝

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 LeetCode。 day 63&#xff0c;周二&#xff0c;ding~ 题目详情 [卡码53] 寻宝 题目描述 卡码53 寻宝 解题思路 前提&#xff1a; 思路&#xff1a; 重点&#xff1a; 代码实现 C语言 prim算法 kruskal…

UDP协议介绍和作用

什么是UDP? UDP是User Datagram Protocol的简称&#xff0c;中文名是用户数据报协议&#xff0c;是OSI参考模型中的传输层协议&#xff0c;它是一种无连接的传输层协议&#xff0c;提供面向事务的简单不可靠信息传送服务。 UDP的正式规范是IETF RFC768。UDP在IP报文的协议号是…

java数组之线性查找、二分法查找

一、线性查找 思想&#xff1a;如果想在一个数组中查找是否有某个元素&#xff0c;最容易想到的办法就是遍历数组&#xff0c;将数组中元素与想要查找的元素逐个对比&#xff0c;如果相等表示找到了&#xff0c;如果不等&#xff0c;则表示没找到。这就是线性查找的思想。 案例…

Chat2DB:AI引领下的全链路数据库管理新纪元

一、引言 随着数据驱动决策成为现代企业和组织的核心竞争力&#xff0c;数据库管理工具的重要性日益凸显。然而&#xff0c;传统的数据库管理工具往往存在操作复杂、功能单一、不支持多类型数据库管理等问题&#xff0c;限制了数据的有效利用。为了打破这一局面&#xff0c;Ch…

东方通Tongweb发布vue前端

一、前端包中添加文件 1、解压vue打包文件 以dist.zip为例&#xff0c;解压之后得到dist文件夹&#xff0c;进入dist文件夹&#xff0c;新建WEB-INF文件夹&#xff0c;进入WEB-INF文件夹&#xff0c;新建web.xml文件&#xff0c; 打开web.xml文件&#xff0c;输入以下内容 …

代码随想录算法训练营第四十九天| 647. 回文子串、 516.最长回文子序列

647. 回文子串 题目链接&#xff1a;647. 回文子串 文档讲解&#xff1a;代码随想录 状态&#xff1a;不会 思路&#xff1a; dp[i][j] 表示字符串 s 从索引 i 到索引 j 这一段子串是否为回文子串。 当s[i]与s[j]不相等&#xff0c;那没啥好说的了&#xff0c;dp[i][j]一定是fa…

Chromium编译指南2024 Linux篇-编译Chromium(五)

1.引言 在完成环境配置之后&#xff0c;我们需要开始实际的编译工作。编译 Chromium 是一个相对复杂且耗时的过程&#xff0c;尤其是第一次编译时。为了保证顺利完成&#xff0c;我们将使用 GN 和 Ninja 工具来生成和管理构建文件。接下来&#xff0c;我们会详细介绍如何生成构…

Cesium中实现全球体积云效果的一种方案

原生 Cesium 提供了一种积云的效果&#xff0c;云的物理特征和渲染性能都还不错&#xff0c;这种方案适合表达小范围相对离散的云朵&#xff0c;但是用来实现全球范围下相对连续、柔和渐变的云层比较困难。本文在体渲染的基础上&#xff0c;参考了开源社区中 shadertoy 和 thre…

软件架构之软件架构概述及质量属性

软件架构之软件架构概述及质量属性 第 9 章&#xff1a;软件架构设计9.1 软件架构概述9.1.1 软件架构的定义9.1.2 软件架构的重要性9.1.3 架构的模型 9.2 架构需求与软件质量属性9.2.1 软件质量属性9.2.2 6 个质量属性及实现 第 9 章&#xff1a;软件架构设计 像学写文章一样&…

java通过poi-tl导出word实战详细步骤

文章目录 与其他模版引擎对比1.引入maven依赖包2.新建Word文档exportWprd.docx模版3.编写导出word接口代码4.导出成果 poi-tl是一个基于Apache POI的Word模板引擎&#xff0c;也是一个免费开源的Java类库&#xff0c;你可以非常方便的加入到你的项目中&#xff0c;并且拥有着让…

模板语法之插值语法{{}}——01

<主要研究&#xff1a;{{ 这里可以写什么}} 1.在data中声明的变量函数都可以 2.常量 3.只要是合法的JavaScript的表达式&#xff0c;都可以 4. 模板表达式都被放在沙盒中&#xff0c;只能访问全局变量的一个白名单&#xff0c;如 Math 和 Date <body> <div i…

进程间的通信--管道

文章目录 一、进程通信的介绍1.1进程间为什么需要通信1.2进程如何通信 二、管道2.1匿名管道2.1.1文件描述符理解管道2.1.2接口使用2.1.3管道的4种情况2.1.4管道的五种特征 2.2管道的使用场景2.2.1命令行中的管道2.2.2进程池 2.命名管道2.1.1原理2.2.2接口2.2.3代码实例 一、进程…