给定一个只含0和1的数组,求含1的最大矩形面积。

Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and return its area.

这样的题一般看来都是有O(n*m)的解法的。

借助上一题Largest Rectangle in Histogram 的解法。

我们现在把矩阵的每一行当做是上一题的问题,然后遍历所有的行数,取最大数就是解。

这里的每一行的高度怎么确定呢。

1.如果当前点为‘0’,那么高度就是0

2.如果当前点为‘1’,那么高度就是往上连续1的个数(包括自己)。

求高度是一个动态规划过程。用dp[i][j]来存某个位置的高度那么

对于第i行第j列的点:

if (matrix[i][j] == '1')
  dp[i][j] = dp[i-1][j] + 1;
else
  dp[i][j] = 0;

class Solution {
public:
//
int largestRectangleArea(vector<int> &height)
{
height.push_back();
int maxarea = ;
int i = ;
stack<int> stk; while(i < height.size())
{
if (stk.empty() || height[stk.top()] < height[i])
{
stk.push(i++);
}
else
{
int t = stk.top();
stk.pop();
maxarea = max(maxarea, height[t]*(stk.empty()?i:i-stk.top()-));
}
}
return maxarea;
}
//
int maximalRectangle(vector<vector<char> > &matrix)
{
if (matrix.size() == || matrix[].size()==) return ;
int row = matrix.size(), col = matrix[].size(), ans = ;
vector<vector<int> > dp(row, vector<int>(col));
for (int j = ; j < col; j++)
dp[][j] = matrix[][j] - '';
for (int i = ; i < row; i++) //动态求每行的histogram高度
for (int j = ; j < col; j++)
{
if (matrix[i][j] == '')
dp[i][j] = dp[i-][j] + ;
else
dp[i][j] = ;
}
for (int i = ; i < row; i++)
{
ans = max(ans, largestRectangleArea(dp[i]));
}
return ans;
}
};

如上是O(n*m)的解法。其实我觉得这个大神的O(n^3)的解法解释也挺好理解。

分析:一般一个题目我首先会想想怎么暴力解决,比如这一题,可以枚举出所有的矩形,求出其中的面积最大者,那么怎么枚举呢,如果分别枚举矩形的宽度和高度,这样还得枚举矩形的位置,复杂度至少为O(n^4) (计算复杂度是我们把matrix的行、列长度都泛化为n,下同),我们可以枚举矩形左上角的位置,那么知道了矩形左上角的位置,怎么计算以某一点为左上角的矩形的最大面积呢?举例如下,下面的矩阵我们以(0,0)为矩形的左上角:

1 1 1 1 0 0

1 1 1 0 1 1

1 0 1 0 1 1

0 1 1 1 1 1

1 1 1 1 1 1

矩形高度是1时,宽度为第一行中从第一个位置起连续的1的个数,为4,面积为4 * 1 = 4

矩形高度是2时,第二行从第一个位置起连续1的个数是3,宽度为min(3,4) = 3,面积为3*2 = 6

矩形高度为3时,第三行从第一个位置起连续1的个数是1,宽度为min(1,3) = 1,面积为1*3 = 3

矩形高度为4时,第四行从第一个位置起连续1的个数是0,宽度为min(0,1) = 0,面积为0*4 = 0

后面的行就不用计算了,因为上一行计算的宽度是0,下面所有宽度都是0

因此以(0,0)为左上角的矩形的最大面积是6,计算以某一点为左上角的矩形的最大面积复杂度是O(n)。

注意到上面我们用到了信息“从某一行某个位置开始连续的1的个数”,这个我们可以通过动态规划求得:设dp[i][j]是从点(i,j)开始,这一行连续1的个数,动态规划方程如下:

  1. 初始条件:dp[i][column-1] = (matrix[i][column-1] == '1') (column是matrix的列数)
  2. dp[i][j] = (matrix[i][j] == '1') ?  1 + dp[i][j + 1] : 0 ,(从方程看出我们应该从每一行的后往前计算)

计算dp复杂度O(n^2),枚举左上角位置以及计算以该位置为左上角的矩形最大面积复杂度是O(n^2*n)=O(n^3),总的复杂度是O(n^3)

这个算法还可以优化,枚举到某个点时我们可以假设该点右下方全是1,得到一个假设最大面积,如果这个面积比当前计算好的面积还要小,该点就可以直接跳过;在上面计算以某点为左上角的矩形面积时,也可以剪枝,剪枝方法同上。具体可以参考代码注释。

class Solution {
public:
int maximalRectangle(vector<vector<char> > &matrix) {
int row = matrix.size();
if(row == )return ;
int column = matrix[].size();
int dp[row][column], res = ;
memset(dp, , sizeof(dp));
//求出所有的dp值
for(int i = ; i < row; i++)
dp[i][column-] = (matrix[i][column-] == '');
for(int i = ; i < row; i++)
for(int j = column - ; j >= ; j--)
if(matrix[i][j] == '')
dp[i][j] = + dp[i][j + ];
//以每个点作为矩形的左上角计算所得的最大矩形面积
for(int i = ; i < row; i++)
{ for(int j = ; j < column; j++)
{
//剪枝,column-j是最大宽度,row-i是最大高度
if((column - j) * (row - i) <= res)break;
int width = dp[i][j];
for(int k = i; k < row && width > ; k++)
{
//剪枝,row-i是以点(i,j)为左上角的矩形的最大高度
if(width * (row - i) <= res)break;
//计算以(i.j)为左上角,上下边缘是第i行和第k行的矩形面积
if(width > dp[k][j])width = dp[k][j];//矩形宽度要取从第i行到第k行宽度的最小值
res = max(res, width * (k - i + ));
}
}
}
return res;
}
};

leetcode[85] Maximal Rectangle的更多相关文章

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

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

  2. LeetCode (85): Maximal Rectangle [含84题分析]

    链接: https://leetcode.com/problems/maximal-rectangle/ [描述] Given a 2D binary matrix filled with '0's ...

  3. [LeetCode] 85. Maximal Rectangle 最大矩形

    Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and ...

  4. leetCode 85.Maximal Rectangle (最大矩阵) 解题思路和方法

    Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and ...

  5. 85. Maximal Rectangle

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

  6. 刷题85. Maximal Rectangle

    一.题目说明 题目,85. Maximal Rectangle,计算只包含1的最大矩阵的面积.难度是Hard! 二.我的解答 看到这个题目,我首先想到的是dp,用dp[i][j]表示第i行第j列元素向 ...

  7. 【LeetCode】85. Maximal Rectangle

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

  8. 【leetcode】85. Maximal Rectangle(单调栈)

    Given a rows x cols binary matrix filled with 0's and 1's, find the largest rectangle containing onl ...

  9. 【leetcode】Maximal Rectangle

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

随机推荐

  1. 通达OA web页面与精灵显示内容更新后不一致的问题

    前一段就发现有这种问题.就是在开发的电话查询里更新的信息,可是在精灵对话窗体上显示的还是原来的信息.这样导致从新开发入口更新信息就不能使用.一開始还以为是厂家升级,变更了存储的表结构.感觉下载近期的升 ...

  2. Spring AOP入门——概念和注意事项

    AOP什么? AOP在功能方面,它是之前和之后运行一些业务逻辑,一些操作(比方记录日志.或者是推断是否有权限等),这些操作的加入.全然不耦合于原来的业务逻辑.从而对原有业务逻辑全然是透明. 也就是说. ...

  3. CodeForces 398B 概率DP 记忆化搜索

    题目:http://codeforces.com/contest/398/problem/B 有点似曾相识的感觉,记忆中上次那个跟这个相似的 我是用了 暴力搜索过掉的,今天这个肯定不行了,dp方程想了 ...

  4. SQL Server 服务器磁盘测试之SQLIO篇

    原文:SQL Server 服务器磁盘测试之SQLIO篇 数据库调优工作中,有一部分是需要排查IO问题的,例如IO的速度或者RAID级别无法响应高并发下的快速请求.最常见的就是查看磁盘每次读写的响应速 ...

  5. cocos2d-x 网络请求

    [cocos2dx]rapidjson用法以及中文显示的解决方法 cocos2dx 读取json及解析 cocos2dx rapidjson 高速解析JSON  --- [cocos2d-x官方文档] ...

  6. SICP 习题 (1.37)解题总结

    SICP 习题 1.37是一条非常长的题目,主要讲的是无穷连分式.无穷连分式对我来说又是一个陌生的概念,于是又去百度了一番,发现无穷连分式也是一个非常有意思的话题,涉及到无理数的表达.只是我建议大家还 ...

  7. [Cocos2d-x]Cocos2d-x 3.2 学习笔记

    获取屏幕大小(Visible) Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Direc ...

  8. MAC OSX在视图port哪个程序占用,杀死进程的方法

    sudo lsof -i :9000 COMMAND   PID    USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME java    6 ...

  9. POJ 2502 Subway (Dijkstra 最短+建设规划)

    Subway Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6689   Accepted: 2176 Descriptio ...

  10. 多普勒失真信号采样Matlab模拟分析

    多普勒失真信号采样Matlab模拟分析 方案 水声通信指的是使用声信号在水中数据传输. 相对而言.电磁信号在水中吸收严重衰减过快,光信号受水中悬浮颗粒的影响,也无法完毕远距离传输. 这两种信号的传播距 ...