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

Example:

Input:
[
["1","0","1","0","0"],
["1","0","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"]
]
Output: 6

此题是之前那道的 Largest Rectangle in Histogram 的扩展,这道题的二维矩阵每一层向上都可以看做一个直方图,输入矩阵有多少行,就可以形成多少个直方图,对每个直方图都调用 Largest Rectangle in Histogram 中的方法,就可以得到最大的矩形面积。那么这道题唯一要做的就是将每一层都当作直方图的底层,并向上构造整个直方图,由于题目限定了输入矩阵的字符只有 '0' 和 '1' 两种,所以处理起来也相对简单。方法是,对于每一个点,如果是 ‘0’,则赋0,如果是 ‘1’,就赋之前的 height 值加上1。具体参见代码如下:

解法一:

class Solution {
public:
int maximalRectangle(vector<vector<char> > &matrix) {
int res = ;
vector<int> height;
for (int i = ; i < matrix.size(); ++i) {
height.resize(matrix[i].size());
for (int j = ; j < matrix[i].size(); ++j) {
height[j] = matrix[i][j] == '' ? : ( + height[j]);
}
res = max(res, largestRectangleArea(height));
}
return res;
}
int largestRectangleArea(vector<int>& height) {
int res = ;
stack<int> s;
height.push_back();
for (int i = ; i < height.size(); ++i) {
if (s.empty() || height[s.top()] <= height[i]) s.push(i);
else {
int tmp = s.top(); s.pop();
res = max(res, height[tmp] * (s.empty() ? i : (i - s.top() - )));
--i;
}
}
return res;
}
};

我们也可以在一个函数内完成,这样代码看起来更加简洁一些,注意这里的 height 初始化的大小为 n+1,为什么要多一个呢?这是因为我们只有在当前位置小于等于前一个位置的高度的时候,才会去计算矩形的面积,假如最后一个位置的高度是最高的,那么我们就没法去计算并更新结果 res 了,所以要在最后再加一个高度0,这样就一定可以计算前面的矩形面积了,这跟上面解法子函数中给 height 末尾加一个0是一样的效果,参见代码如下:

解法二:

class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
if (matrix.empty() || matrix[].empty()) return ;
int res = , m = matrix.size(), n = matrix[].size();
vector<int> height(n + );
for (int i = ; i < m; ++i) {
stack<int> s;
for (int j = ; j < n + ; ++j) {
if (j < n) {
height[j] = matrix[i][j] == '' ? height[j] + : ;
}
while (!s.empty() && height[s.top()] >= height[j]) {
int cur = s.top(); s.pop();
res = max(res, height[cur] * (s.empty() ? j : (j - s.top() - )));
}
s.push(j);
}
}
return res;
}
};

下面这种方法的思路很巧妙,height 数组和上面一样,这里的 left 数组表示若当前位置是1且与其相连都是1的左边界的位置(若当前 height 是0,则当前 left 一定是0),right 数组表示若当前位置是1且与其相连都是1的右边界的位置再加1(加1是为了计算长度方便,直接减去左边界位置就是长度),初始化为n(若当前 height 是0,则当前 right 一定是n),那么对于任意一行的第j个位置,矩形为 (right[j] - left[j]) * height[j],我们举个例子来说明,比如给定矩阵为:

[
[1, 1, 0, 0, 1],
[0, 1, 0, 0, 1],
[0, 0, 1, 1, 1],
[0, 0, 1, 1, 1],
[0, 0, 0, 0, 1]
]

第0行:

h:
l:
r:

第1行:

h:
l:
r:

第2行:

h:
l:
r:

第3行:

h:
l:
r:

第4行:

h:
l:
r:

解法三:

class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
if (matrix.empty() || matrix[].empty()) return ;
int res = , m = matrix.size(), n = matrix[].size();
vector<int> height(n, ), left(n, ), right(n, n);
for (int i = ; i < m; ++i) {
int cur_left = , cur_right = n;
for (int j = ; j < n; ++j) {
if (matrix[i][j] == '') {
++height[j];
left[j] = max(left[j], cur_left);
} else {
height[j] = ;
left[j] = ;
cur_left = j + ;
}
}
for (int j = n - ; j >= ; --j) {
if (matrix[i][j] == '') {
right[j] = min(right[j], cur_right);
} else {
right[j] = n;
cur_right = j;
}
res = max(res, (right[j] - left[j]) * height[j]);
}
}
return res;
}
};

再来看一种解法,这里我们统计每一行的连续1的个数,使用一个数组 h_max, 其中 h_max[i][j] 表示第i行,第j个位置水平方向连续1的个数,若 matrix[i][j] 为0,那对应的 h_max[i][j] 也一定为0。统计的过程跟建立累加和数组很类似,唯一不同的是遇到0了要将 h_max 置0。这个统计好了之后,只需要再次遍历每个位置,首先每个位置的 h_max 值都先用来更新结果 res,因为高度为1也可以看作是矩形,然后我们向上方遍历,上方 (i, j-1) 位置也会有 h_max 值,但是用二者之间的较小值才能构成矩形,用新的矩形面积来更新结果 res,这样一直向上遍历,直到遇到0,或者是越界的时候停止,这样就可以找出所有的矩形了,参见代码如下:

解法四:

class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
if (matrix.empty() || matrix[].empty()) return ;
int res = , m = matrix.size(), n = matrix[].size();
vector<vector<int>> h_max(m, vector<int>(n));
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (matrix[i][j] == '') continue;
if (j > ) h_max[i][j] = h_max[i][j - ] + ;
else h_max[i][] = ;
}
}
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (h_max[i][j] == ) continue;
int mn = h_max[i][j];
res = max(res, mn);
for (int k = i - ; k >= && h_max[k][j] != ; --k) {
mn = min(mn, h_max[k][j]);
res = max(res, mn * (i - k + ));
}
}
}
return res;
}
};

类似题目:

Maximal Square

Largest Rectangle in Histogram

参考资料:

https://leetcode.com/problems/maximal-rectangle/

https://leetcode.com/problems/maximal-rectangle/discuss/29054/Share-my-DP-solution

https://leetcode.com/problems/maximal-rectangle/discuss/29172/My-O(n3)-solution-for-your-reference

https://leetcode.com/problems/maximal-rectangle/discuss/225690/Java-solution-with-explanations-in-Chinese

https://leetcode.com/problems/maximal-rectangle/discuss/29064/A-O(n2)-solution-based-on-Largest-Rectangle-in-Histogram

LeetCode All in One 题目讲解汇总(持续更新中...)

[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

    给定一个只含0和1的数组,求含1的最大矩形面积. Given a 2D binary matrix filled with 0's and 1's, find the largest rectangl ...

  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(单调栈)

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

  8. 【LeetCode】85. Maximal Rectangle

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

  9. 【leetcode】Maximal Rectangle

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

随机推荐

  1. LeetCode 189:旋转数组 Rotate Array

    公众号:爱写bug(ID:icodebugs) 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数. Given an array, rotate the array to the ...

  2. jwt入门

    JWT(JSON Web Token)是一个非常轻巧的规范,这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息,通常使用在HTTP通信过程中进行身份认证. 我们知道,HTTP通信是无状态的 ...

  3. Linux(CentOS)启动时自动执行脚本(rc.local)

    下面说说通过rc.local文件进行开机启动 1.首先创建一个启动脚本,这里以启动docker为例 创建 docker-startup.sh 脚本 #! /bin/bash /usr/bin/mk-d ...

  4. Grafana的Docker部署方式

    docker run -d -p : --name=grafana544 -v D:/grafana/grafana-/data:/var/lib/grafana -v D:/grafana/graf ...

  5. 创建vue3项目

    最近准备做一个vue的小项目关于vue3的使用. 首先在vscode全局安装vue脚手架,npm i -g @vue/cli. 然后创建vue项目,vue create mydemo(项目名). 接下 ...

  6. Javaweb常用解决问题连接

    1.javaweb的idea如何创建及配置web项目 https://www.jianshu.com/p/8d49d36a3c7e 2.servlet的建立以及部署 https://blog.csdn ...

  7. 妹纸对网易严选的Bra是什么评价?

    声明:这是一篇超级严肃的技术文章,请本着学习交流的态度阅读,谢谢! 一.网易商品评论爬取 1.评论分析 进入到网易严选官网,搜索“文胸”后,先随便点进一个商品. 在商品页面,打开 Chrome 的控制 ...

  8. https申请证书并部署到网站流程,浏览器验证证书流程

    https申请证书并部署到网站流程: 1.生成一对秘钥,设公钥为pubk1,私钥为prik12.假设发布的网站地址为https://www.example.com3.生成一个CSR文件(Cerific ...

  9. Flutter 安装笔记

    一. 安装镜像(有vpn的不用理) 1  打开终端 输入 open ~  ,回车 2  双击 .bash_profile  3  添加以下代码 后保存关闭即可(代码可能会变请直接到https://fl ...

  10. UITableView与UITableViewCell

    转自:http://blog.sina.com.cn/s/blog_4cd14afb01014j97.html UITableView用来以表格的形式显示数据.关于UITableView,我们应该注意 ...