当前位置: 首页 > news >正文

【算法专题训练】24、单调栈

1、单调栈

  • 保存在栈中的数据是排序的,用这种排序的栈来解决问题的方法称为单调栈法
  • 如何使用? 在入栈前需要判断与栈顶元素的大小,当栈顶元素更小时执行入栈,栈顶元素更大时不断出栈。

2、LCR 039. 柱状图中最大的矩形

题目信息:

  • https://leetcode.cn/problems/0ynMMM/description/
给定非负整数数组 heights ,数组中的数字用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。示例 1:
输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10示例 2:
输入: heights = [2,4]
输出: 4提示:
1 <= heights.length <=105
0 <= heights[i] <= 104

3、解题思路:

3.1、解法一:暴力解法

  • 两层for循环确定矩形的宽度,在这个宽度区间范围内查找高度最低的元素值,并求最终的矩形面积进行比较,最后返回最大矩形面积
  • 时间复杂度为N的平方,执行超时
int largestRectangleArea1(vector<int> &heights)
{int res = 0;int count = heights.size();for (int i = 0; i < count; i++){int minH = heights[i];for (int j = i; j < count; j++){// 查找最小值if (heights[j] < minH){minH = heights[j];}int area = minH * (j - i + 1);// std::cout << "i:" << i << " ,minH:" << minH << ",area:" << area << std::endl;res = std::max(res, area);}}return res;
}

3.2、解法二:分治法:

  • 在数组元素内找到最小值,以最小元素值为基准将数组分为三个区间,分别求这三个区间的矩形面积,
  • 左右两个区间可以继续拆分,直到区间范围为1个宽度
int realArea(int left, int right, vector<int> &heights)
{std::cout << "left:" << left << " ,right:" << right << std::endl;if (left >= heights.size()){return 0;}if (left >= right) // 区间范围只有一个{return heights[left];}// 找到该区间最小值,再分成三个部分,继续递归遍历int minI = left;for (int i = left; i <= right; i++){if (heights[i] < heights[minI]){minI = i;}}int leftA = realArea(left, minI - 1, heights);int area = heights[minI] * (right - left + 1);int rightA = 0;if (minI < heights.size()){rightA = realArea(minI + 1, right, heights);}area = std::max(area, leftA);return std::max(area, rightA);
}int largestRectangleArea2(vector<int> &heights)
{return realArea(0, heights.size() - 1, heights);
}

3.3、解法三:单调栈解法

  • 单调栈是要求在遍历数组元素的过程中,每一个遍历区间,单调栈中的元素都保持升序排序。
  • 例如数组遍历过程中存在n个区间[0,0],[0,2]… [0,n-1] ,在這些区间过程中单调栈中的元素都保持升序
  • 所以数组遍历过程中,需要判断遍历元素与栈顶元素的大小,如果遍历元素更大,则元素入栈,单调栈数据维持升序
    • 如果遍历元素更小,那要保证该区间范围内,单调栈的升序,那就需要将栈顶元素出栈,继续判断新的栈顶元素与遍历元素的大小,
    • 直至遍历元素更大(while循环),然后执行入栈,这样能保证除了栈顶哪个元素比他小,中间区域比遍历元素大的数据都出栈了,此时遍历元素就是该中间区域的最小值
  • 当栈顶元素出栈时,该元素是中间区域的最小值,以该元素为高度,并进行出栈,宽度为遍历元素位置和新的栈顶元素之间范围。进行求矩形面积
  • 栈中元素保存的是数组元素的下标,为更方便计算中间区域的宽度,默认将-1位置入栈
int largestRectangleArea(vector<int> &heights)
{std::stack<int> stack;stack.push(-1);int res = 0;// 遍历数组for (int i = 0; i < heights.size(); i++){// 遍历元素与栈顶元素判断,遇到栈顶元素比遍历元素大的要进行出栈while (stack.top() != -1 && heights[stack.top()] >= heights[i]){int topI = stack.top();stack.pop();// 计算面积int area = heights[topI] * (i - stack.top() - 1);res = std::max(res, area);}// 并且最终遍历元素要入栈stack.push(i);}// 遍历完后,栈中还有元素,继续while (stack.top() != -1){int topI = stack.top();stack.pop();// 计算面积int area = heights[topI] * (heights.size() - stack.top() - 1);res = std::max(res, area);}return res;
}

4、总结:

  • 单调栈解法需要在入栈时判断与栈顶元素值的大小
  • 矩形面积通过出栈时的元素高度,该高度为中间区域的最小值,区域的宽度为遍历位置与新的栈顶元素位置之间
http://www.dtcms.com/a/398406.html

相关文章:

  • 【开题答辩全过程】以 IRWT考试预约系统为例,包含答辩的问题和答案
  • 在字典和列表相互嵌套的结构体中搜索指定元素
  • 文献阅读 | iMetaMed | FigureYa:一个标准化可视化框架,用于增强生物医学数据解释和研究效率
  • wordpress自由拖拽同ip网站做排名seo
  • 面向运动障碍患者的语音识别新突破:零样本实时专家混合自适应方法详解
  • 校园网站建设的维护制作触屏版网站开发
  • 零衍门户组件联邦模式:重新定义组件开发新体验!
  • 【Web前端|第一篇】HTML、CSS与JavaScript
  • 有手机网站了还要微网站吗所有的网站都要用htmlu做吗
  • 面向对象设计:构建可维护、可扩展的软件系统
  • 52.haproxy负载均衡
  • 什么是“智能体”?
  • 负载均衡式在线OJ项目复盘
  • 【Golang】数据设计模式
  • 新建免费网站软件关键词排名
  • 小迪安全v2023学习笔记(八十六讲)—— FridaHOOK证书提取SSL双向校验绕过
  • 律师事务所网站方案网站 建设 初期规划
  • 舒适化诊疗的关键支持:伟荣局部麻醉器械使用体验
  • Kanass入门到实战(1) - 安装教程
  • 【Linux系统】深入理解线程同步,实现生产消费模型
  • 【2025-系统规划与管理师】第六章:云资源规划
  • JDK17 新特性梳理
  • ZooKeeper源码分析与实战-模块一:基础篇
  • 网站建设 优势网站开发需求报告
  • jikuaiarc项目构建,参考arc,把arc一直到antlr4,生成g4文件
  • 白话讲讲GenAI、LLM、Agent、RAG、LangChain
  • (25.09)使用Livox-mid-360录制数据并运行Fast-lio2命令
  • 【图文】Codex接入Kimi K2/GLM-4.5 环境配置指南 (Windows/macOS/Ubuntu)
  • 异步 vs 同步:JavaScript中的速度与激情
  • Django模型与数据表的映射方式详解:不止Code First与Database First