LintCode 510: Maximal Rectangle
LintCode 510: Maximal Rectangle
题目描述
给你一个二维矩阵,权值为False和True,找到一个最大的矩形,使得里面的值全部为True,输出它的面积
Wed Nov 24 2016
思路
本题的思路比较多,可以用动态规划,也可以把本题看做是最长连续正数列的二维版本,还可以把本题看做多个求柱形图中得最大矩形问题。
如果用动态规划,记\(f(i, j, l)\)为以\((i, j)\)为左上角顶点,以\(l\)为列宽的矩形面积。指定\(i\),\(j\),通过变换\(l\),可以得到以\(i\),\(j\)为顶点的最大矩形面积。通过遍历\(i\),\(j\),可求出最终答案。此方法的时间复杂度为\(O(mn^2)\)。
对于连续最长正数列,只需从头到尾遍历一遍即可,用一个变量记录当前最大的长度,当遇到0时重置长度计数。应用到二维情况则是遍历左上角顶点和右下角顶点,时间复杂度是\(O(m^2n^2)\)。
对于在柱状图中求最大矩形,可以构造一个递增栈,使得求解的时间复杂度为\(O(n)\),应用到二维情况就是\(O(mn)\)。
在一维的问题中,给的数据是一个数列,第i个数表示第i个位置的柱形的高度。从数列的第一个数开始,依次将它们入栈,直到当前准备入栈的高度小于栈顶元素的高度为止。这样就维护了一个递增的序列。
此时就可以计算一次矩形的面积了。矩形的高度就是当前栈顶元素位置柱状图的高度,矩形的宽度就是从当前准备入栈却又没有入栈的元素的位置到栈顶的距离。同时栈顶元素出栈。
若栈顶出栈后当前准备入栈的元素高度还是小于当前栈顶元素的高度,则继续出栈,计算方法跟上面的一样,之所以可以直接用当前准备入栈又还没入栈的元素与栈顶元素的距离来表示矩形的宽度,是因为当前栈顶的元素是从栈顶到准备入栈元素之间所有柱状图中高度最矮的(比它高的都出栈了)。
如此循环,直到当前元素的高度比栈顶元素的高度高了,再正常入栈。
此方法中每个元素只有一次机会入栈,所以时间复杂度是\(O(n)\)。
应用到二维的问题中,其实就是把矩阵看作是多个柱状图的叠加。对于每一行,把那一行作为柱状图的横坐标,那一行以上1的个数就是该位置柱形的高度,那一行以下的部分忽略不计。在计算高度的时候,若某位置的元素是1,则该位置的高度等于上一行相同位置的高度加1,否则就直接是0。这样计算高度的算法的时间复杂度也是\(O(mn)\),总体的时间复杂度不变。
代码
// 从矩形中计算各个柱状图的高度
void getBarHeights(vector<vector<bool> > &matrix, vector<vector<int> > &heights)
{
int n = matrix.size();
int m = matrix[0].size();
vector<int> tmp;
for (vector<bool>::iterator iter = matrix[0].begin(); iter != matrix[0].end(); ++iter)
tmp.push_back(*iter);
heights.push_back(tmp);
for (int i = 1; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
if (matrix[i][j] == 0)
tmp[j] = 0;
else
tmp[j]++;
}
heights.push_back(tmp);
}
}
// 柱状图求最大矩形算法
int maxBarRec(vector<int>& height)
{
int max = 0;
int n = height.size();
stack<int> s;
for (int i = 0; i <= n; ++i)
{
int h = i == n ? 0 : height[i];
if (s.empty() || h > height[s.top()]) s.push(i);
else
{
while (!s.empty() && h <= height[s.top()])
{
int crr = s.top(); s.pop();
int area = height[crr] * (s.empty() ? i : i - s.top() - 1);
if (area > max) max = area;
}
--i;
}
}
return max;
}
// 主函数
int maximalRectangle(vector<vector<bool> > &matrix)
{
int m = matrix.size();
if (m <= 0) return 0;
int n = matrix[0].size();
int max = 0;
vector<vector<int> > heights;
getBarHeights(matrix, heights);
for (int i = m - 1; i >= 0; --i)
{
int tmax = maxBarRec(heights[i]);
if (tmax > max) max = tmax;
}
return max;
}
LintCode 510: Maximal Rectangle的更多相关文章
- [LintCode] Maximal Rectangle 最大矩形
Given a 2D boolean matrix filled with False and True, find the largest rectangle containing all True ...
- 85. Maximal Rectangle
85. Maximal Rectangle Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle c ...
- 求解最大矩形面积 — leetcode 85. Maximal Rectangle
之前切了道求解最大正方形的题,题解猛戳 这里.这道题 Maximal Rectangle 题意与之类似,但是解法完全不一样. 先来看这道题 Largest Rectangle in Histogram ...
- 【leetcode】Maximal Rectangle
Maximal Rectangle Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle conta ...
- 47. Largest Rectangle in Histogram && Maximal Rectangle
Largest Rectangle in Histogram Given n non-negative integers representing the histogram's bar height ...
- leetcode Maximal Rectangle 单调栈
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4052721.html 题目链接:leetcode Maximal Rectangle 单调栈 ...
- leetcode面试准备: Maximal Rectangle
leetcode面试准备: Maximal Rectangle 1 题目 Given a 2D binary matrix filled with 0's and 1's, find the larg ...
- LeetCode之“动态规划”:Maximal Square && Largest Rectangle in Histogram && Maximal Rectangle
1. Maximal Square 题目链接 题目要求: Given a 2D binary matrix filled with 0's and 1's, find the largest squa ...
- 最大的矩形面积 Maximal Rectangle
2018-09-15 10:23:44 一.Largest Rectangle in Histogram 在求解最大的矩形面积之前,我们先讨论一条最大直方图面积的问题. 问题描述: 问题求解: 解法一 ...
随机推荐
- lintcode-427-生成括号
427-生成括号 给定 n 对括号,请写一个函数以将其生成新的括号组合,并返回所有组合结果. 样例 给定 n = 3, 可生成的组合如下: "((()))", "(()( ...
- Windows Forms编程实战学习:第一章 初识Windows Forms
初识Windows Forms 1,用C#编程 using System.Windows.Forms; [assembly: System.Reflection.AssemblyVersion(& ...
- DB2 V9 默认帐户信息和服务启动信息
1 dasusr1 DB2 管理服务器用户是管理DAS(Database Adminitrator Service).要完全适用db2 cc 必须启动DAS.DB2 管理服务器(DAS)响应来自 DB ...
- java分页算法
int totalPageNum = (totalRecord + pageSize - 1) / pageSize;
- 【转】关于cgi、FastCGI、php-fpm、php-cgi
转自 知乎 的 一个回答 首先,CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的,方便CGI程序的编写者. web server(比如说nginx)只是内容的分发者.比如 ...
- c语言----程序记录
1.结构体写入文件,读取 #include <stdio.h> #include <string.h> #include <stdlib.h> #define ma ...
- PHP面向对象之重载
重载技术overloading 重载的基本概念 重载在“通常面向对象语言”中的含义: 是指,在一个类(对象)中,有多个名字相同但形参不同的方法的现象: 类似这样: class C{ functio ...
- IPv4编址及子网划分
在讨论IP编址之前,我们需要讨论一下主机与路由器连入网络的方法.一台主机通常只有一条链路链接到网络:当主机中的IP想发送一个数据报时,它就在链路上发送,主机与物理链路之间的边界叫做接口(interfa ...
- 【bzoj5123】[Lydsy12月赛]线段树的匹配 树形dp+记忆化搜索
题目描述 求一棵 $[1,n]$ 的线段树的最大匹配数目与方案数. $n\le 10^{18}$ 题解 树形dp+记忆化搜索 设 $f[l][r]$ 表示根节点为 $[l,r]$ 的线段树,匹配选择根 ...
- 【bzoj4425】[Nwerc2015]Assigning Workstations分配工作站 贪心+堆
题目描述 佩内洛普是新建立的超级计算机的管理员中的一员. 她的工作是分配工作站给到这里来运行他们的计算研究任务的研究人员. 佩内洛普非常懒惰,不喜欢为到达的研究者们解锁机器. 她可以从在她的办公桌远程 ...