给定一个只含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. 使用PF_PACKET和SOCK_RAW发送自己定义type以太网数据包

    本文介绍使用PF_PACKET和SOCK_RAW发送自己定义type以太网数据包,使用wireshare抓包能够获取到数据包,为Linux内核添加网络协议做铺垫. 先上码: #include < ...

  2. 【git学习五】git基础之git分支

    1.背景                最早用github的时候,我傻傻的问舍友大神,git里面的branch是干什么的,他用了非常直白的解释,我至今还记得."branch就是你能够自己建立 ...

  3. C++内存分配和拷贝构造函数写研究

    昨晚参加笔试,开错题,有印象中的概念,但目前尚不清楚是怎么回事,什么原理,导致错误的话题.现在总结. 一.C++写内存分配研究 问题考察例如以下,请先不要看答案,看看你是否能做对,呵呵: waterm ...

  4. 第20章 状态模式(State Pattern)

    原文 第20章 状态模式(State Pattern) 状态模式  概述:   当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要解决的是当控制一个对象状态的条件表 ...

  5. 第21章 策略模式(Strategy Pattern)

    原文 第21章 策略模式(Strategy Pattern) 策略模式 导读:策略模式看完之后,大多数人都会感觉有点混了,包括我,感觉策略模式是一种OO思想的体现(纯属个人拙见). 概述:       ...

  6. Handler详细说明系列(六)——View的post()详解

    MainActivity例如下列: package cc.testui2; import android.os.Bundle; import android.view.View; import and ...

  7. sgu 194 被动散热器具有最大流量的上限和下限(最大流量模板dinic加上优化)

    模板类型的题详细參考国家集训队论文:http://wenku.baidu.com/view/0f3b691c59eef8c75fbfb35c.html 參考博客:http://blog.csdn.ne ...

  8. 【UVA】580-Critical Mass

    依据递推公式计算,须要打表不然可能会超时. #include<cstdio> #include<cstring> #include<iostream> #inclu ...

  9. 【百度地图API】如何判断点击的是地图还是覆盖物?

    原文:[百度地图API]如何判断点击的是地图还是覆盖物? 摘要:很多API爱好者问我,为什么我点击的是marker,而map也会响应该事件呢?怎样才能判断,我点击的是标注,还是地图呢?下面一起来看看. ...

  10. 开发者:网站 & SDK

    { 收集的一些.开发工具 } Teambition 团队协作工具 GitCafe 代码托管 FIR.im App 托管平台 Coding 代码托管,项目管理,WebIDE 计蒜客 编程学习 SendC ...