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 异常注意事项

    异常的注意事项:   1,子类在覆盖父类方法时,父类的方法如果抛出了异常, 那么子类的方法只能抛出父类的异常或者该异常的子类.   2,如果父类抛出多个异常,那么子类只能抛出父类异常的子集.     ...

  2. jquery mobiscroll 滑动、滚动

    mobiscroll : 滑动选择 2.13.2版本免费,官网(mobiscroll.com)收费 先从官方下载2.13.2体验版下来,查看例子结合官方API学习( http://docs.mobis ...

  3. 一个form表单,多个提交按钮

    技巧就是把提交的input的类型改成button!这样就可以实现多个按钮提交! 以下是案例: <form action="" id="tijiao"> ...

  4. PHP对象类型转换

    其他数据类型转换为对象类型 其他数据类型转换为对象类型,得到的结果是:内置标准类(stdclass)的一个对象! 语法形式为: $obj1  =  (object) 其他类型数据: 数组转换为对象:数 ...

  5. free word online

    free word online https://office.live.com/start/Word.aspx https://www.lifewire.com/free-online-word-p ...

  6. ZOJ3591_Nim

    题目的意思是给你n个ai,有多少种不同的连续段使得用该段数中所有的数字玩Nim游戏的先手必胜. 首先根据博弈论的知识,我们知道,要使先手必胜,那么只要保证所有的数的异或值不为0就可以了. 这个题目,给 ...

  7. HDU2460-Network

    题目 给一个\(n\)个点\(m\)条边的无向连通图,\(Q\)次往图中加边,每次加边后问图中的桥有多少个.(加边后边留着). \(n\le 10^5,m\le 2\times 10^5,Q\le 1 ...

  8. 【bzoj5183】[Baltic2016]Park 离线+对偶图+并查集

    题目描述 在Byteland的首都,有一个矩形围栏围起来的公园.在这个公园里树和访客都以一个圆形表示.公园有四个出入口,每个角落一个(1=左下角,2=右下角,3=右上角,4=左上角).访客能通过这些出 ...

  9. android面试(2)----组件

    1.anroid:id的作用? android:id是作为控件的唯一标示符.可以使用与releativelayout中,也可以再Activity中通过findviewbyid来获得指定的控件. 2.a ...

  10. java执行cmd命令并获取输出结果

    1.java执行cmd命令并获取输出结果 import java.io.BufferedReader; import java.io.InputStreamReader; import org.apa ...