leetcode[85] Maximal Rectangle
给定一个只含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的个数,动态规划方程如下:
- 初始条件:dp[i][column-1] = (matrix[i][column-1] == '1') (column是matrix的列数)
- 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的更多相关文章
- 求解最大矩形面积 — leetcode 85. Maximal Rectangle
之前切了道求解最大正方形的题,题解猛戳 这里.这道题 Maximal Rectangle 题意与之类似,但是解法完全不一样. 先来看这道题 Largest Rectangle in Histogram ...
- LeetCode (85): Maximal Rectangle [含84题分析]
链接: https://leetcode.com/problems/maximal-rectangle/ [描述] Given a 2D binary matrix filled with '0's ...
- [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 ...
- leetCode 85.Maximal Rectangle (最大矩阵) 解题思路和方法
Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and ...
- 85. Maximal Rectangle
85. Maximal Rectangle Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle c ...
- 刷题85. Maximal Rectangle
一.题目说明 题目,85. Maximal Rectangle,计算只包含1的最大矩阵的面积.难度是Hard! 二.我的解答 看到这个题目,我首先想到的是dp,用dp[i][j]表示第i行第j列元素向 ...
- 【LeetCode】85. Maximal Rectangle
Maximal Rectangle Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle conta ...
- 【leetcode】85. Maximal Rectangle(单调栈)
Given a rows x cols binary matrix filled with 0's and 1's, find the largest rectangle containing onl ...
- 【leetcode】Maximal Rectangle
Maximal Rectangle Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle conta ...
随机推荐
- sdut 在机器上面向对象编程练习11(运算符重载)
在机器上面向对象编程练习11(运算符重载) Time Limit: 1000MS Memory limit: 65536K 标题叙述性说明 有两个矩阵a和b,均为2行3列,求两个矩阵之和.重载运算符& ...
- P90
#include<stdio.h> #define N 4 int fun(int a[][N]) { int i,j,max=a[0][0]; for(i=0;i<2;i++) f ...
- 第四章:Django 的模板系统(转)
在之前的章节中,你可能觉得例子中视图返回文本有点不妥.即是, HTML 是直接写在 Python 代码中的. 这种做法会导致这些问题: 要做任何设计上的更改就必须改写 Python 代 ...
- Git与TortoiseGit基本操作(转)
1. GitHub操作 本节先简单介绍 git 的使用与操作, 然后再介绍 TortoiseGit 的使用与操作. 先看看SVN的操作吧, 最常见的是 检出(Check out ...), 更新 (U ...
- SpringData JPA的学习笔记之环境搭建
一.环境搭建 1.加入jar包 spring jar+jpa jar +springData jar >>SpringData jar包 2.配置applicationCont ...
- hdu Oulipo(kmp)
Problem Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, w ...
- C++语言债券系列之十一——友元函数和拷贝构造函数
1.好友功能 (1)友元函数类的普通功能外定义. 定义友元函数和相同的正常功能.在类必须声明的正常功能为好友. (2)友元函数不是一个成员函数. 你不能反对打电话.但直接调用:友元函数访问类的公共.p ...
- MySql创建一个存储过程
MySQL 存储过程是从 MySQL 5.0 新功能.存储过程的长处有一箩筐.只是最基本的还是运行效率和SQL 代码封装. 特别是 SQL 代码封装功能,假设没有存储过程,在外部程序訪问数据库时(比如 ...
- 数据结构之Huffman树与最优二叉树
最近在翻炒一些关于树的知识,发现一个比较有意思的二叉树,huffman树,对应到离散数学中的一种名为最优二叉树的路径结构,而Huffman的主要作用,最终可以归结到一种名为huffman编码的编码方式 ...
- Cocos2d-x 3.2 大富翁游戏项目开发-第五部分 单机游戏-级别选择ScrollView
于MenuScene.cpp 点击单机游戏后会调用 Director::getInstance()->pushScene(MapChooseScene::createScene()); 进入到关 ...