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:

  1. Input:
  2. [
  3. ["1","0","1","0","0"],
  4. ["1","0","1","1","1"],
  5. ["1","1","1","1","1"],
  6. ["1","0","0","1","0"]
  7. ]
  8. Output: 6

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

解法一:

  1. class Solution {
  2. public:
  3. int maximalRectangle(vector<vector<char> > &matrix) {
  4. int res = ;
  5. vector<int> height;
  6. for (int i = ; i < matrix.size(); ++i) {
  7. height.resize(matrix[i].size());
  8. for (int j = ; j < matrix[i].size(); ++j) {
  9. height[j] = matrix[i][j] == '' ? : ( + height[j]);
  10. }
  11. res = max(res, largestRectangleArea(height));
  12. }
  13. return res;
  14. }
  15. int largestRectangleArea(vector<int>& height) {
  16. int res = ;
  17. stack<int> s;
  18. height.push_back();
  19. for (int i = ; i < height.size(); ++i) {
  20. if (s.empty() || height[s.top()] <= height[i]) s.push(i);
  21. else {
  22. int tmp = s.top(); s.pop();
  23. res = max(res, height[tmp] * (s.empty() ? i : (i - s.top() - )));
  24. --i;
  25. }
  26. }
  27. return res;
  28. }
  29. };

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

解法二:

  1. class Solution {
  2. public:
  3. int maximalRectangle(vector<vector<char>>& matrix) {
  4. if (matrix.empty() || matrix[].empty()) return ;
  5. int res = , m = matrix.size(), n = matrix[].size();
  6. vector<int> height(n + );
  7. for (int i = ; i < m; ++i) {
  8. stack<int> s;
  9. for (int j = ; j < n + ; ++j) {
  10. if (j < n) {
  11. height[j] = matrix[i][j] == '' ? height[j] + : ;
  12. }
  13. while (!s.empty() && height[s.top()] >= height[j]) {
  14. int cur = s.top(); s.pop();
  15. res = max(res, height[cur] * (s.empty() ? j : (j - s.top() - )));
  16. }
  17. s.push(j);
  18. }
  19. }
  20. return res;
  21. }
  22. };

下面这种方法的思路很巧妙,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. [
  2. [1, 1, 0, 0, 1],
  3. [0, 1, 0, 0, 1],
  4. [0, 0, 1, 1, 1],
  5. [0, 0, 1, 1, 1],
  6. [0, 0, 0, 0, 1]
  7. ]

第0行:

  1. h:
  2. l:
  3. r:

第1行:

  1. h:
  2. l:
  3. r:

第2行:

  1. h:
  2. l:
  3. r:

第3行:

  1. h:
  2. l:
  3. r:

第4行:

  1. h:
  2. l:
  3. r:

解法三:

  1. class Solution {
  2. public:
  3. int maximalRectangle(vector<vector<char>>& matrix) {
  4. if (matrix.empty() || matrix[].empty()) return ;
  5. int res = , m = matrix.size(), n = matrix[].size();
  6. vector<int> height(n, ), left(n, ), right(n, n);
  7. for (int i = ; i < m; ++i) {
  8. int cur_left = , cur_right = n;
  9. for (int j = ; j < n; ++j) {
  10. if (matrix[i][j] == '') {
  11. ++height[j];
  12. left[j] = max(left[j], cur_left);
  13. } else {
  14. height[j] = ;
  15. left[j] = ;
  16. cur_left = j + ;
  17. }
  18. }
  19. for (int j = n - ; j >= ; --j) {
  20. if (matrix[i][j] == '') {
  21. right[j] = min(right[j], cur_right);
  22. } else {
  23. right[j] = n;
  24. cur_right = j;
  25. }
  26. res = max(res, (right[j] - left[j]) * height[j]);
  27. }
  28. }
  29. return res;
  30. }
  31. };

再来看一种解法,这里我们统计每一行的连续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,或者是越界的时候停止,这样就可以找出所有的矩形了,参见代码如下:

解法四:

  1. class Solution {
  2. public:
  3. int maximalRectangle(vector<vector<char>>& matrix) {
  4. if (matrix.empty() || matrix[].empty()) return ;
  5. int res = , m = matrix.size(), n = matrix[].size();
  6. vector<vector<int>> h_max(m, vector<int>(n));
  7. for (int i = ; i < m; ++i) {
  8. for (int j = ; j < n; ++j) {
  9. if (matrix[i][j] == '') continue;
  10. if (j > ) h_max[i][j] = h_max[i][j - ] + ;
  11. else h_max[i][] = ;
  12. }
  13. }
  14. for (int i = ; i < m; ++i) {
  15. for (int j = ; j < n; ++j) {
  16. if (h_max[i][j] == ) continue;
  17. int mn = h_max[i][j];
  18. res = max(res, mn);
  19. for (int k = i - ; k >= && h_max[k][j] != ; --k) {
  20. mn = min(mn, h_max[k][j]);
  21. res = max(res, mn * (i - k + ));
  22. }
  23. }
  24. }
  25. return res;
  26. }
  27. };

类似题目:

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. Vue.js 源码分析(十五) 指令篇 v-bind指令详解

    指令是Vue.js模板中最常用的一项功能,它带有前缀v-,比如上面说的v-if.v-html.v-pre等.指令的主要职责就是当其表达式的值改变时,相应的将某些行为应用到DOM上,先介绍v-bind指 ...

  2. Vue 结合 SignalR 实现前后端实时消息同步

    最近业务中需要实现服务器端与客户端的实时通信功能,对Signalr做了一点总结和整理. SignalR 作为  ASP.NET 的一个库,能够简单方便地为应用提供实时的服务器端与客户端双向通信功能. ...

  3. Python自定义注解

    Python3.0之后加入新特性Decorators,以@为标记修饰function和class.有点类似c++的宏和java的注解.Decorators用以修饰约束function和class,分为 ...

  4. [Docker] Win10中安装Docker并运行Nginx镜像

    一.安装Docker 进入官网:https://www.docker.com/products/docker-desktop 可能需要先注册登录,很简单的. 点击 Download Desktop f ...

  5. xiaohacontainer, docker, windows-来自微软Azure CTO的布道

    https://azure.microsoft.com/zh-cn/blog/containers-docker-windows-and-trends/ 今天这个时代当你讨论云计算时,不谈谈docke ...

  6. Python传入参数的几种方法

    写在前面 Python唯一支持的参数传递方式是『共享传参』(call by sharing) 多数面向对象语言都采用这一模式,包括Ruby.Smalltalk和Java(Java的引用类型是这样,基本 ...

  7. Python【day 10】函数进阶-小结

    本节主要内容1.动态参数 *args **kwargs 形参:*args将多个位置参数聚合打包成元组 **kwargs将多个关键字参数聚合打包成字典 实参:*li1将列表进行解包打散成多个位置参数 * ...

  8. element-ui Upload 上传组件源码分析整理笔记(十四)

    简单写了部分注释,upload-dragger.vue(拖拽上传时显示此组件).upload-list.vue(已上传文件列表)源码暂未添加多少注释,等有空再补充,先记下来... index.vue ...

  9. Java基础之 集合体系结构(Collection、List、ArrayList、LinkedList、Vector)

    Java基础之 集合体系结构详细笔记(Collection.List.ArrayList.LinkedList.Vector) 集合是JavaSE的重要组成部分,其与数据结构的知识密切相联,集合体系就 ...

  10. 图解Java数据结构之双向链表

    上一篇文章说到了单链表,也通过案例具体实现了一下,但是单链表的缺点也显而易见. 单向链表查找的方向只能是一个方向 单向链表不能自我删除,需要靠辅助节点 而双向链表则能够很轻松地实现上面的功能. 何为双 ...