【单调栈]LeetCode84: 柱状图中最大的矩形

作者推荐

【动态规划】【广度优先搜索】LeetCode:2617 网格图中最少访问的格子数

本文涉及的知识点

单调栈

题目

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

分析

时间复杂度😮(n)。

枚举

如何不重复不遗漏的枚举所有子数组,最容易想到的枚举子数组的起点和终点[left,right]。这样的时间复杂度是O(n2),超时。 可以枚举子数组的最小高度heights[i],再枚举left[i],right[i]。left[i]的取值范围(x1,i]。x1是从i-1到0,第一个heights[x1]<heights[i],如果不存在,令x1等于-1。right[i]的取值范围[i,x2)。x2是从i+1,到n-1 第一个heights[x2] <= heights[i],如果不存在,令x2等于m_c。由于要求最大面积,所以left[i]取最小值,right[i]取最大值。即:矩形最底低在i时,宽度最大的子数组为(left[i],right[i])。
x1是小于,x2是小于等于的含义是:如果有多个最低处,以最右边的为准。
符合以下三个条件:

两个子状态都有序
新增的数据有序
查询有序

vLeftHeightIndex

vLeftHeightIndex记录下标和高度。如果i1 < i2,且heights[i1] >= heights[i2],则i1被淘汰了。淘汰后,下标升序,高度也升序。新增加的数据下标也是按升序加入,这是可以优化成单调栈(向量)的条件。
vLeftHeightIndex.back() 被淘汰,说明heights[i]小于等于vLeftHeightIndex.back(),而且是第一个小于等于的高度。也就是vRight。

代码,

核心代码

class Solution {
public:
	int largestRectangleArea(vector<int>& heights) {
		m_c = heights.size();
		vector<pair<int, int>> vLeftHeightIndex;
		vector<int> vLeftFirstLess(m_c,-1), vRightFirstMoreEqual(m_c,m_c);//别忘记初始化
		for (int i = 0; i < m_c; i++)
		{
			while (vLeftHeightIndex.size() && (heights[i]  <= vLeftHeightIndex.back().first ))
			{
				vRightFirstMoreEqual[vLeftHeightIndex.back().second] = i;
				vLeftHeightIndex.pop_back();				
			}
			if (vLeftHeightIndex.size())
			{
				vLeftFirstLess[i] = vLeftHeightIndex.back().second;
			}
			vLeftHeightIndex.emplace_back(heights[i], i);
		}
		int iRet = 0;
		for (int i = 0; i < m_c; i++)
		{
			iRet = max(iRet, heights[i] * (vRightFirstMoreEqual[i] - vLeftFirstLess[i] - 1));
		}
		return iRet;
	}
	int m_c;
};

测试用例

template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() != v2.size())
	{
		assert(false);
		return;
	}
	for (int i = 0; i < v1.size(); i++)
	{
		assert(v1[i] == v2[i]);
	}
}

template<class T>
void Assert(const T& t1, const T& t2)
{
	assert(t1 == t2);
}

int main()
{
	vector<int> heights;
	int r;
	{
		Solution slu;		
		heights = { 2, 1, 5, 6, 2, 3 };
		auto res = slu.largestRectangleArea(heights);
		Assert(10, res);
	}
	{
		Solution slu;
		heights = { 2,4 };
		auto res = slu.largestRectangleArea(heights);
		Assert(4, res);
	}
}

2023年3月旧代码

class Solution {
public:
int largestRectangleArea(vector& heights) {
m_c = heights.size();
vector vMaxLeft;
{
vector<std::pair<int, int>> vLeft;
for (int i = 0; i < heights.size(); i++)
{
const int& h = heights[i];
const int iLessNum = std::lower_bound(vLeft.begin(), vLeft.end(), h, [](const std::pair<int, int>& p, const int i)
{
return p.first < i;
}) - vLeft.begin();
if (0 == iLessNum)
{
vMaxLeft.push_back(-1);
}
else
{
vMaxLeft.push_back(vLeft[iLessNum - 1].second);
}
while (vLeft.size() && (vLeft.back().first >= h))
{
vLeft.pop_back();
}
vLeft.emplace_back(h, i);
}
}
int iMax = INT_MIN;
{
vector<std::pair<int, int>> vRight;
for (int i = m_c - 1; i >= 0; i–)
{
const int& h = heights[i];
const int iLessNum = std::lower_bound(vRight.begin(), vRight.end(), h+1, [](const std::pair<int, int>& p, const int i)
{
return p.first < i;
}) - vRight.begin();
if (0 == iLessNum)
{
iMax =max(iMax, h * (m_c - vMaxLeft[i]-1));
}
else
{
const int iRight = vRight[iLessNum - 1].second;
iMax = max(iMax, h * (iRight - vMaxLeft[i]-1));
}
while (vRight.size() && (vRight.back().first >= h))
{
vRight.pop_back();
}
vRight.emplace_back(h, i);
}
}
return iMax;
}
int m_c;
};

2023年8月

class Solution {
public:
int largestRectangleArea(vector& heights) {
m_c = heights.size();
vector vLeft(m_c, -1), vRight(m_c, m_c);
stack sta;
for (int i = 0; i < heights.size(); i++)
{
while (sta.size() && (heights[i] <= heights[sta.top()] ))
{
vRight[sta.top()] = i;
sta.pop();
}
if (sta.size())
{
vLeft[i] = sta.top();
}
sta.emplace(i);
}
int iRet = 0;
for (int i = 0; i < m_c; i++)
{
iRet = max(iRet, (vRight[i] - vLeft[i] - 1) * heights[i]);
}
return iRet;
}
int m_c;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【JVM从入门到实战】(七)运行时数据区的组成

运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域&#xff0c;称之为运行时数据区。 《Java虚拟机规范》中规定了每一部分的作用 线程不共享&#xff1a;程序计数器、虚拟机栈、本地方法栈 线程共享&#xff1a;方法区&#xff0c;堆 1. 程序计数器(Program Count…

代码随想录刷题题Day14

刷题的第十四天&#xff0c;希望自己能够不断坚持下去&#xff0c;迎来蜕变。&#x1f600;&#x1f600;&#x1f600; 刷题语言&#xff1a;C Day14 任务 ● 110.平衡二叉树 ● 257. 二叉树的所有路径 ● 404.左叶子之和 1 平衡二叉树 二叉树节点的深度&#xff1a;指从根节…

​LeetCode解法汇总1631. 最小体力消耗路径

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 描述&#xff1a; 你准备参…

spring 笔记八 SpringMVC异常处理和SpringMVC拦截器

文章目录 SpringMVC拦截器拦截器&#xff08;interceptor&#xff09;的作用拦截器和过滤器区别拦截器是快速入门拦截器方法说明 SpringMVC拦截器拦截器&#xff08;interceptor&#xff09;的作用拦截器和过滤器区别拦截器是快速入门拦截器方法说明 SpringMVC异常处理异常处理…

JMeter安装RabbitMQ测试插件

整体流程如下&#xff1a;先下载AMQP插件源码&#xff0c;可以通过antivy在本地编译成jar包&#xff0c;再将jar包导入JMeter目录下&#xff0c;重启JMeter生效。 Apache Ant 是一个基于 Java 的构建工具。Ant 可用于自动化构建和部署 Java 应用程序&#xff0c;使开发人员更轻…

MATLAB 计算点云坐标的最大最小值 (38)

MATLAB 计算点云坐标的最大最小值 (38) 一、算法介绍二、算法实现1.代码一、算法介绍 沿着X Y Z三个坐标轴方向,点云坐标存在对应的最大最小值,这在计算点云体积或者其他方面有使用,这里使用MATLAB快速获取xmax xmin ymax ymin zmax zmin6个最大最小值 二、算法实现 1.代…

jmeter,断言:响应断言、Json断言

一、响应断言 接口A请求正常返回值如下&#xff1a; {"status": 10013, "message": "user sign timeout"} 在该接口下创建【响应断言】元件&#xff0c;配置如下&#xff1a; 若断言成功&#xff0c;则查看结果树的接口显示绿色&#xff0c;若…

nodejs+vue+微信小程序+python+PHP的微博网络舆情分析系统-计算机毕业设计推荐

2.3.1 功能性分析 按照微博网络舆情分析系统的角色&#xff0c;我划分为了微博用户管理模块和管理员管理模块这三大部分。 微博用户管理模块&#xff1a;&#xff08;1&#xff09;用户登录&#xff1a;用户登录微博网络舆情分析系统 &#xff1b;用户对个人信息的增删改查&…

python每日学11:xpath的使用与调试

背景&#xff1a;最近在使用selenium 模拟浏览器作一些常规操作&#xff0c;在使用selenium的过程中接触到的一种定位方法&#xff0c;叫xpath, 这里说一下使用心得。 首先&#xff0c;我觉得如果只是简单使用的话是不用详细了解具体的语法规则的。 一、xpath怎么用&#xff1…

Linux 内存池源码剖析

1 传统的分配与释放内存的函数缺点: void *malloc(size_t size); void *calloc(size_t nmemb,size_t size);void *realloc(void *ptr, size_t size);void free(void *ptr);缺点1: 高并发时较小内存块使用导致系统调用频繁,降低了系统的执行效率 缺点2: 频繁使用时增加了系统…

【Unity】简单实现生成式电子围栏

【Unity】简单实现生成式电子围栏 三维电子围栏是一种通过使用三维技术和电子设备来建立虚拟围栏&#xff0c;用于监控和控制特定区域的系统。它可以通过使用传感器和摄像头来检测任何越界行为&#xff0c;并及时发出警报。这种技术可以应用于安防领域以及其他需要对特定区域进…

Repo代码仓库搭建

使用rockchip sdk二次开发&#xff0c;代码十几个G&#xff0c;都放在一个git仓库的话&#xff0c;每次git status要等好久&#xff0c;决定拆分一下&#xff0c;官方是用repo做代码管理的&#xff0c;我打算也搭建个类似开发环境。 1.首先在git服务器上创建一个manifest仓库&…

【深度学习目标检测】六、基于深度学习的路标识别(python,目标检测,yolov8)

YOLOv8是一种物体检测算法&#xff0c;是YOLO系列算法的最新版本。 YOLO&#xff08;You Only Look Once&#xff09;是一种实时物体检测算法&#xff0c;其优势在于快速且准确的检测结果。YOLOv8在之前的版本基础上进行了一系列改进和优化&#xff0c;提高了检测速度和准确性。…

【Docker】ES、Kibana及IK安装配置

目录 一.单节点安装部署 1.版本选择 2.推荐及总结 ​3.官网下载地址 4.创建网络 5.拉取镜像 6.创建文件夹 7.运行docker命令 二、安装kibana 1.安装kibana 2.浏览器访问 3.国际化 三、Elasticsearch查询 1.数据插入&#xff1a;POST或PUT 2.数据查询GET 3.分词…

最新Redis7主从复制(保姆级教程)

前提准备&#xff1a;三台云服务器&#xff08;吐血消费&#xff0c;点赞回血&#xff09;也可以使用虚拟机创建三台&#xff0c;但是我搞了一天也连接不上&#xff0c;要是又可以连接上的大家可以教我一下&#xff0c;也可以参考一下或者大家可以参考一下这个大佬的配置&#…

Postgresql在Windows中使用pg_dump实现数据库(指定表)的导出与导入

场景 Windows中通过bat定时执行命令和mysqldump实现数据库备份&#xff1a; Windows中通过bat定时执行命令和mysqldump实现数据库备份_mysqldump bat-CSDN博客 Windows上通过bat实现不同数据库之间同步部分表的部分字段数据&#xff1a; Windows上通过bat实现不同数据库之间…

Parade Series - Message Interaction

if (true) {Swal.fire("节目发布", "发布完毕", "success");event.preventDefault(); } if (false) {Swal.fire("节目发布", "发布失败", "error");event.preventDefault(); }if (true) {for (var i 0; i < b…

柔性数组(结构体成员)

目录 前言&#xff1a; 柔性数组&#xff1a; 给柔性数组分配空间&#xff1a; 调整柔性数组大小&#xff1a; 柔性数组的好处&#xff1a; 前言&#xff1a; 柔性数组&#xff1f;可能你从未听说&#xff0c;但是确实有这个概念。听名字&#xff0c;好像就是柔软的数…

各技术栈需要掌握的知识

一、前端工程师需要掌握的知识 前端工程师需要掌握的知识主要包括以下几个方面: HTML、CSS和JavaScript:这是前端工程师的基础知识,需要熟练掌握。HTML是网页的骨架,CSS是网页的外观和样式,JavaScript则是实现网页交互效果的关键。响应式设计:随着移动设备的普及,响应…

华为数通——企业双出口冗余

目标&#xff1a;默认数据全部经过移动上网&#xff0c;联通低带宽。 R1 [ ]ip route-static 0.0.0.0 24 12.1.1.2 目的地址 掩码 下一条 [ ]ip route-static 0.0.0.0 24 13.1.1.3 preference 65 目的地址 掩码 下一条 设置优先级为65 R…
最新文章