[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 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;
- }
- };
类似题目:
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
LeetCode All in One 题目讲解汇总(持续更新中...)
[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
给定一个只含0和1的数组,求含1的最大矩形面积. Given a 2D binary matrix filled with 0's and 1's, find the largest rectangl ...
- 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(单调栈)
Given a rows x cols binary matrix filled with 0's and 1's, find the largest rectangle containing onl ...
- 【LeetCode】85. Maximal Rectangle
Maximal Rectangle Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle conta ...
- 【leetcode】Maximal Rectangle
Maximal Rectangle Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle conta ...
随机推荐
- Vue.js 源码分析(十五) 指令篇 v-bind指令详解
指令是Vue.js模板中最常用的一项功能,它带有前缀v-,比如上面说的v-if.v-html.v-pre等.指令的主要职责就是当其表达式的值改变时,相应的将某些行为应用到DOM上,先介绍v-bind指 ...
- Vue 结合 SignalR 实现前后端实时消息同步
最近业务中需要实现服务器端与客户端的实时通信功能,对Signalr做了一点总结和整理. SignalR 作为 ASP.NET 的一个库,能够简单方便地为应用提供实时的服务器端与客户端双向通信功能. ...
- Python自定义注解
Python3.0之后加入新特性Decorators,以@为标记修饰function和class.有点类似c++的宏和java的注解.Decorators用以修饰约束function和class,分为 ...
- [Docker] Win10中安装Docker并运行Nginx镜像
一.安装Docker 进入官网:https://www.docker.com/products/docker-desktop 可能需要先注册登录,很简单的. 点击 Download Desktop f ...
- xiaohacontainer, docker, windows-来自微软Azure CTO的布道
https://azure.microsoft.com/zh-cn/blog/containers-docker-windows-and-trends/ 今天这个时代当你讨论云计算时,不谈谈docke ...
- Python传入参数的几种方法
写在前面 Python唯一支持的参数传递方式是『共享传参』(call by sharing) 多数面向对象语言都采用这一模式,包括Ruby.Smalltalk和Java(Java的引用类型是这样,基本 ...
- Python【day 10】函数进阶-小结
本节主要内容1.动态参数 *args **kwargs 形参:*args将多个位置参数聚合打包成元组 **kwargs将多个关键字参数聚合打包成字典 实参:*li1将列表进行解包打散成多个位置参数 * ...
- element-ui Upload 上传组件源码分析整理笔记(十四)
简单写了部分注释,upload-dragger.vue(拖拽上传时显示此组件).upload-list.vue(已上传文件列表)源码暂未添加多少注释,等有空再补充,先记下来... index.vue ...
- Java基础之 集合体系结构(Collection、List、ArrayList、LinkedList、Vector)
Java基础之 集合体系结构详细笔记(Collection.List.ArrayList.LinkedList.Vector) 集合是JavaSE的重要组成部分,其与数据结构的知识密切相联,集合体系就 ...
- 图解Java数据结构之双向链表
上一篇文章说到了单链表,也通过案例具体实现了一下,但是单链表的缺点也显而易见. 单向链表查找的方向只能是一个方向 单向链表不能自我删除,需要靠辅助节点 而双向链表则能够很轻松地实现上面的功能. 何为双 ...