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的更多相关文章

  1. [LintCode] Maximal Rectangle 最大矩形

    Given a 2D boolean matrix filled with False and True, find the largest rectangle containing all True ...

  2. 85. Maximal Rectangle

    85. Maximal Rectangle Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle c ...

  3. 求解最大矩形面积 — leetcode 85. Maximal Rectangle

    之前切了道求解最大正方形的题,题解猛戳 这里.这道题 Maximal Rectangle 题意与之类似,但是解法完全不一样. 先来看这道题 Largest Rectangle in Histogram ...

  4. 【leetcode】Maximal Rectangle

    Maximal Rectangle Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle conta ...

  5. 47. Largest Rectangle in Histogram && Maximal Rectangle

    Largest Rectangle in Histogram Given n non-negative integers representing the histogram's bar height ...

  6. leetcode Maximal Rectangle 单调栈

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4052721.html 题目链接:leetcode Maximal Rectangle 单调栈 ...

  7. leetcode面试准备: Maximal Rectangle

    leetcode面试准备: Maximal Rectangle 1 题目 Given a 2D binary matrix filled with 0's and 1's, find the larg ...

  8. 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 ...

  9. 最大的矩形面积 Maximal Rectangle

    2018-09-15 10:23:44 一.Largest Rectangle in Histogram 在求解最大的矩形面积之前,我们先讨论一条最大直方图面积的问题. 问题描述: 问题求解: 解法一 ...

随机推荐

  1. Java package

    Java中的一个包就是一个类库单元,包内包含有一组类,它们在单一的名称空间之下被组织在了一起.这个名称空间就是包名.可以使用import关键字来导入一个包.例如使用import java.util.* ...

  2. oracle和DB2的差异

    1.简介 当今IT的环境正经历着剧烈的变化,依靠单一的关系型数据库管理系统(RDBMS)管理数据的公司开始逐渐减少.分析家的报告指出 ,今天超过90%的公司都拥有不只一种RDBMS.在现在紧张的经济情 ...

  3. jQuery的2把利器

    <!-- $是一个函数,首先是给window添加$,然后该值是一个函数,函数返回的值是对象.1. jQuery核心函数 * 简称: jQuery函数($/jQuery) * jQuery库向外直 ...

  4. DHCP:动态主机配置协议

    DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)是一个局域网的网络协议,使用UDP协议工作, 主要有两个用途:给内部网络或网络服务供应商自动分配IP ...

  5. 第195天:js---函数对象详解(call、apply)

    一.call 1.call供爷法则 // 对象1 var myclass={ getAllStudentsNumbers:function(num1,num2){ return num1+num2; ...

  6. Appium自动化测试框架

    1.在utils包中创建一个AppiumUtil类,这个类是对appium api进行封装的. 代码如下: package utils; import java.net.MalformedURLExc ...

  7. 【JavaScript&jQuery】轮展图

    用bootstrap实现轮展图和用Jquery自定义轮展图两种   1.使用bootstrap插件 效果图: 用一个超简单的方法,那就是用bootstrap的插件,什么?不懂bootstrap?没关系 ...

  8. (转)linux下压缩和归档相关命令tar,zip,gzip,bzip2

    压缩包也有两种形式,一种是tar.gz包(.tgz包也是这种),一种是tar.bz2包. tar.gz包的解压方法:tar zxvf [PackageName].tar.gz tar.bz2包的解压方 ...

  9. 3.5 面向连接的运输:TCP

    3.5  面向连接的运输:TCP 3.5.1 TCP连接 TCP进行传输之间要进行三次握手建立连接,这个连接不是物理意义上的有一根电线连接,而是应用端两个应用,在逻辑上是已经建立连接了. TCP 不需 ...

  10. [AT2369] [agc013_c] Ants on a Circle

    题目链接 AtCoder:https://agc013.contest.atcoder.jp/tasks/agc013_c 洛谷:https://www.luogu.org/problemnew/sh ...