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. .net 错误处理

    第一步在页面中写OnError方法: protected override void OnError(EventArgs e) { Exception ex = Server.GetLastError ...

  2. 使用 python 管理 mysql 开发工具箱 - 2

    这篇博文接着上篇文章<使用 python 管理 mysql 开发工具箱 - 1>,继续写下自己学习 python 管理 MySQL 中的知识记录. 一.MySQL 的读写分离 学习完 My ...

  3. Maven基本理解

    转 maven(一) maven到底是个啥玩意~ 我记得在搞懂maven之前看了几次重复的maven的教学视频.不知道是自己悟性太低还是怎么滴,就是搞不清楚,现在弄清楚了,基本上入门了.写该篇博文,就 ...

  4. java 使用volatile实现线程数据的共享

    java 使用volatile实现线程数据的共享 直接上代码看效果: public class VolatileTest extends Thread { private volatile boole ...

  5. BZOJ3875 AHOI2014/JSOI2014骑士游戏(动态规划)

    容易想到设f[i]为杀死i号怪物所消耗的最小体力值,由后继节点更新.然而这显然是有后效性的,正常的dp没法做. 虽然spfa已经死了,但确实还是挺有意思的.只需要用spfa来更新dp值就可以了.dij ...

  6. ubuntu成功安装搜狗输入法

    在安装之前,我们要先了解一个事实,那就是linux下安装软件和Windows是非常不同的,并不是简单地双击安装包就可以安装了.linux很多软件都有自己的一个依赖源,如果不先安装好这些依赖源,你是无法 ...

  7. CF1093F Vasya and Array DP

    题面 题面 \(\Delta\)题面有点问题,应该是数列中没有长度大于等于\(len\)的连续数字才是合法的. 题解 设\(f[i][j]\)表示DP到\(i\)位,以\(j\)为结尾的方案数, \( ...

  8. kerberos中的spn详解

    0x01 SPN定义    服务主体名称(SPN)是Kerberos客户端用于唯一标识给特定Kerberos目标计算机的服务实例名称.Kerberos身份验证使用SPN将服务实例与服务登录帐户相关联. ...

  9. bzoj2296: 【POJ Challenge】随机种子(思维题/水题)

    有点类似CF某场div2T1... 前面接上1234567890000000,后面加上x+(1234567890000000%x)就可以保证是x的倍数了 #include<iostream> ...

  10. 洛谷 P1486 BZOJ 1503 NOI 2004 郁闷的出纳员 fhq treap

    思路: 1. 此处的fhq treap的分裂是按照权值分裂然后插入的.将小于k的分为一棵子树,大于等于k的分为另一棵子树. 2. 删除的时候只要将大于等于min的分裂到以root为根的树中,另一部分不 ...