【单调栈】【区间合并】LeetCode85:最大矩形

作者推荐

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

本文涉及的知识点

单调栈 区间合并

题目

给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。
示例 1:
输入:matrix = [[“1”,“0”,“1”,“0”,“0”],[“1”,“0”,“1”,“1”,“1”],[“1”,“1”,“1”,“1”,“1”],[“1”,“0”,“0”,“1”,“0”]]
输出:6
解释:最大矩形如上图所示。
示例 2:
输入:matrix = [[“0”]]
输出:0
示例 3:
输入:matrix = [[“1”]]
输出:1
参数范围
rows == matrix.length
cols == matrix[0].length
1 <= row, cols <= 200
matrix[i][j] 为 ‘0’ 或 ‘1’

分析

时间复杂度O(n2m)。枚举矩形的left和right,时间复杂度o(n^2)。指定left,right,计算连续1的数量大于等于width的行数,时间复杂度O(m)。

代码

核心代码

class Solution {
public:
	int maximalRectangle(vector<vector<char>>& matrix) {
		m_r = matrix.size();
		m_c = matrix.front().size();
		vector<vector<int>> vRightLen(m_r, vector<int>(m_c));
		for (int r = 0; r < m_r; r++)
		{
			for (int c = m_c - 1; c >= 0; c--)
			{
				if ('1' == matrix[r][c])
				{
					vRightLen[r][c] = 1 + ((m_c - 1 == c) ? 0 : vRightLen[r][c + 1]);
				}
			}
		}
		int iRet = 0;
		for (int left = 0; left < m_c; left++)
		{
			for (int right = left; right < m_c; right++)
			{
				const int width = right - left + 1;
				int height = 0;
				for (int r = 0; r < m_r; r++)
				{
					if (vRightLen[r][left] < width)
					{
						iRet = max(iRet, height * width);
						height = 0;
					}
					else
					{
						height++;
					}
				}
				iRet = max(iRet, height * width);
			}
		}
		return iRet;
	}
	int m_r, 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<vector<char>> matrix;
	int r;
	{
		Solution slu;		
		matrix = { {'1','0','1','0','0'},{'1','0','1','1','1'},{'1','1','1','1','1'},{'1','0','0','1','0'} };
		auto res = slu.maximalRectangle(matrix);
		Assert(6, res);
	}
	{
		Solution slu;
		matrix = { {'0'} };
		auto res = slu.maximalRectangle(matrix);
		Assert(0, res);
	}
	{
		Solution slu;
		matrix = { {'1'} };
		auto res = slu.maximalRectangle(matrix);
		Assert(1, res);
	}
	{
		Solution slu;
		matrix = { {'1','1'}};
		auto res = slu.maximalRectangle(matrix);
		Assert(2, res);
	}
	{
		Solution slu;
		matrix = { {'1'},{'1' } };
		auto res = slu.maximalRectangle(matrix);
		Assert(2, res);
	}
}

单调栈

枚举底部,本题就可以转化成柱形图的最大矩形

class Solution {
public:
	int maximalRectangle(vector<vector<char>>& matrix) {		
		m_c = matrix.front().size();
		vector<int> vHeights(m_c);
		int iRet = 0;
		for (int r = 0; r < matrix.size(); r++)
		{
			for (int c = m_c - 1; c >= 0; c--)
			{
				if ('1' == matrix[r][c])
				{
					vHeights[c] +=1 ;
				}
				else
				{
					vHeights[c] = 0 ;
				}
			}
			iRet = max(iRet, largestRectangleArea(vHeights));
		}
		return iRet;
	}
	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;
};

2022年12月版代码

 class Solution {
 public:
	 int maximalRectangle(vector<vector<char>>& matrix) {
		 m_r = matrix.size();
		 m_c = matrix[0].size();
		 vector<vector<int>> leftNums;
		 leftNums.assign(m_r, vector<int>(m_c));
		 for (int r = 0; r < m_r; r++)
		 {
			 for (int c = 0; c < m_c; c++)
			 {
				 if ('0' == matrix[r][c])
				 {
					 leftNums[r][c] = 0;
				 }
				 else
				 {
					 leftNums[r][c] = 1 + ((c > 0) ? leftNums[r][c - 1] : 0);
				 }
			 }
		 }
		 		 
		 for (int c = 0; c < m_c; c++)
		 {
			 stack<pair<int, int>> sta;			 
			 for (int r = 0; r < m_r; r++)
			 {
				 int iMinR = r;
				 while (sta.size() && (sta.top().first > leftNums[r][c]))
				 {
					 PopStack(sta, iMinR, r);
				 }
				 if (sta.empty() || (sta.top().first < leftNums[r][c]))
				 {
					 sta.emplace(leftNums[r][c], iMinR);
				 }
			 }
			 
			 while (sta.size())
			 {
				 int iMinR = m_r;
				 PopStack(sta, iMinR, m_r);
			 }
		 }
		 return m_iMaxArea;
	 }
	 void PopStack(stack<pair<int, int>>& sta,int& iMinRow,int r )
	 {
		 int iWidth = sta.top().first;
		 iMinRow = sta.top().second;

		 sta.pop();
		 m_iMaxArea = max(m_iMaxArea, iWidth*(r - 1 - iMinRow + 1));
	 }
	 int m_r, m_c;
	 int m_iMaxArea = 0;
 };

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步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++**实现。

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

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

相关文章

黑马头条--day01.环境搭建

一.前言 该项目学习自黑马程序员&#xff0c;由我整理如下&#xff0c;版权归黑马程序员所有 二.环境搭建 1.数据库 第一天&#xff0c;先创建如下库和表: sql文件如下: CREATE DATABASE IF NOT EXISTS leadnews_user DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_…

VBA快速填充缺失数据

实例需求&#xff1a;数据表中F列中存在数据缺失&#xff0c;如下图所示。现需要根据A列中的内容&#xff08;类别&#xff0c;图中C1、C2、B1为不同类别&#xff09;&#xff0c;补充F列数据&#xff0c;已知每个类别中F列存在不少于一个非空单元格&#xff0c;并且其内容相同…

OpenAI发布了一份提示工程指南(Prompt Engineering Guide)

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版&#xff0c;欢迎购买。点击进入详情 Open AI 发布了一份很棒的提示工程指南。 以下是在 GPT-4 使用提示时获得更好结果的 6 种策略的总结:

机器学习算法---回归

1. 线性回归&#xff08;Linear Regression&#xff09; 原理&#xff1a; 通过拟合一个线性方程来预测连续响应变量。线性回归假设特征和响应变量之间存在线性关系&#xff0c;并通过最小化误差的平方和来优化模型。优点&#xff1a; 简单、直观&#xff0c;易于理解和实现。…

瑞友天翼应用虚拟化系统 多处SQL 注入漏洞复现(可RCE)

0x01 产品简介 瑞友天翼应用虚拟化系统是西安瑞友信息技术资讯有限公司研发的具有自主知识产权,基于服务器计算架构的应用虚拟化平台。它将用户各种应用软件集中部署在瑞友天翼服务器(群)上,客户端通过WEB即可快速安全的访问经服务器上授权的应用软件,实现集中应用、远程接…

vue中iframe标签跨域通信——父子页面之间传值(解决子页面收不到父页面的值或子页面收到的数据为undefined的问题)

背景 因为本系统需要支持第三方系统页面的嵌入&#xff0c;于是尝试使用iframe标签&#xff0c;进行跨域通信&#xff0c;父子页面相互传值。初始化时&#xff0c;父页面发送数据给子页面&#xff0c;需要在子页面加载完成后发送&#xff0c;不然接收不到数据。父页面直接给子页…

js 高阶(含vue.js)

1、主动触发函数 this.$options.watch.watchOrdersFormPrice.apply(this);//主动触发watchOrdersFormPrice watch:{watchOrdersFormPrice: function(){if( !this.ordersForm.alone_sold_price && this.ordersForm.ginfo.goods_id ){var price_info this.ordersForm.…

uni-app微信小程序隐藏左上角返回按钮

官方文档链接&#xff1a;uni.setNavigationBarTitle(OBJECT) | uni-app官网 (dcloud.net.cn) 首先要明确的是页面间的跳转方式有几种、每一种默认的作用是什么。 uniapp五种跳转方式 第一&#xff1a;wx.navigatorTo 【新页面打开&#xff0c;默认会有返回按钮】第二&#x…

电脑自动关机怎么设置?

电脑自动关机怎么设置&#xff1f;如果你是一名上班族&#xff0c;工作忙起来很多事情都会忘记做&#xff0c;有时候忙到很晚后紧急下班&#xff0c;就会忘记给电脑关机&#xff0c;电脑如果经常不关机&#xff0c;那么电脑就会超负荷的运转&#xff0c;大家都知道电脑的寿命是…

jsp 健身房管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 健身房管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&a…

【系统设计】如何确保消息不会丢失?

一、前言 对于大部分业务系统来说&#xff0c;丢消息意味着数据丢失&#xff0c;是完全无法接受的。其实&#xff0c;现在主流的消息队列产品都提供了非常完善的消息可靠性保证机制&#xff0c;完全可以做到在消息传递过程中&#xff0c;即使发生网络中断或者硬件故障&#xf…

CMake创建wxWidgets桌面应用

CMake创建wxWidgets桌面应用 环境 Windows 10CMake 3.28MinGW 64 8.1wxWidgets 3.2.4 wxWidgets GitHub: https://github.com/wxWidgets/wxWidgets/文档地址: https://docs.wxwidgets.org/stable/page_topics.html下载地址&#xff1a;https://www.wxwidgets.org/downloads…

新版Edge(120) 侧边栏copilot消失解决办法

edge浏览器自动更新了&#xff0c;更新后侧边栏的copilot&#xff08;以前的New Bing&#xff09;图标没了查了网上的各种方法&#xff0c;说的比较多的是安装Edge Dev, 改地址等等&#xff0c;都比较麻烦&#xff0c;再装一个Edge也是不爽。终于在B站的评论里看到一个贼方便的…

python【matplotlib】鼠标拖动滚动缩放坐标范围和拖动图例共存

背景 根据前面的博文&#xff1a; python【matplotlib】画图鼠标缩放拖动动态改变坐标轴范围 和Python【Matplotlib】图例可拖动改变位置 两个博文&#xff0c;博主考虑了一下&#xff0c;如何将两者的功能结合起来&#xff0c;让二者共存。 只需根据Python【Matplotlib】鼠标…

代码随想录-刷题第二十八天

93. 复原 IP 地址 题目链接&#xff1a;93. 复原 IP 地址 思路&#xff1a;切割问题&#xff0c;原理上还是抽象成树形结构&#xff0c;然后使用回溯法。 131 题的要求是&#xff1a;让你把字符串 s 切分成若干个合法的回文串&#xff0c;返回所有的切分方法。 本题的要求是…

iOS_给View的部分区域截图 snapshot for view

文章目录 1.将整个view截图返回image&#xff1a;2.截取view的部分区域&#xff0c;返回image&#xff1a;3.旧方法&#xff1a;4.Tips参考&#xff1a; 1.将整个view截图返回image&#xff1a; 这些 api 已被废弃&#xff0c;所以需要判断 iOS 版本 写两套代码&#xff1a; R…

vue中实现PDF文件流预览

代码示例 <template><div class"print"><div v-if"!viewShow" class"opt-box"><div style"height: 700px; overflow: auto;"><el-table :data"tableData" border><el-table-column prop…

2019年第八届数学建模国际赛小美赛A题放射性产生的热量解题全过程文档及程序

2019年第八届数学建模国际赛小美赛 A题 放射性产生的热量 原题再现&#xff1a; 假设我们把一块半衰期很长的放射性物质做成一个特定的形状。在这种材料中&#xff0c;原子核在衰变时会以随机的方向释放质子。我们假设携带质子的能量是一个常数。质子在穿过致密物质时&#x…

详谈前端中常用的加/密算法

本文主要详细介绍了在前端开发中常用的加/解密算法&#xff0c;以及前端如何实现。 总的来说&#xff1a;前端加密无论使用哪个加密都一样是有可能性被他人获取到相关的公钥或密钥的&#xff08;比如&#xff1a;拦截请求、查看源代码等&#xff09;&#xff0c;然后进行加密与…

深入理解网络 I/O:单 Selector 多线程|单线程模型

&#x1f52d; 嗨&#xff0c;您好 &#x1f44b; 我是 vnjohn&#xff0c;在互联网企业担任 Java 开发&#xff0c;CSDN 优质创作者 &#x1f4d6; 推荐专栏&#xff1a;Spring、MySQL、Nacos、Java&#xff0c;后续其他专栏会持续优化更新迭代 &#x1f332;文章所在专栏&…