首页 简历|笔试面试
您现在的位置:百分网 > 职场 > 笔试面试 > LeetCode

85.最大矩形

  • 25年9月4日 发布
  • 195.56KB 共6页
85.最大矩形85.最大矩形85.最大矩形85.最大矩形85.最大矩形

85. 最大矩形

题意

给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩

形,并返回其面积。

难度

困难

示例

示例 1:

085.%E6%9C%80%E5%A4%A7%E7%9F%A9%E5%BD%A2-20231001074238.png

输入:matrix = [

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

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

["1","1","1","1","1"],

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

输出:6

解释:最大矩形如上图所示。

示例 2:

输入:matrix = []

输出:0

示例 3:

输入:matrix = [["0"]]

输出:0

示例 4:

输入:matrix = [["1"]]

输出:1

示例 5:

输入:matrix = [["0","0"]]

输出:0

分析

本题如果直接入手会非常困难,但之前我们已经做过 084.柱状图中最大的矩形 这题,两

题之间还是有一些共性的,我们来挖掘一下。

首先,我们来看这样一个情况:

085.%E6%9C%80%E5%A4%A7%E7%9F%A9%E5%BD%A2-20231001074513.png

是不是有点眼熟,这不就是一个 heights = [3,2,2,1] 求最大矩形面积吗?

针对这种情况,我们似乎直接套用 084.柱状图中最大的矩形 的题解即可。

来看一下题目描述:

• 084 题:给定一个数组,每个值表示柱子的高度,找出能够勾勒出来的矩形的最大面

积。

• 085 题:给定一个二维矩阵,其中只包含 ‘1’ 和 ‘0’,找出只包含 ‘1’ 的矩形的最大面

积。

分析一下它们之间的关系:

• 为了解决 085 题,我们可以使用 084 题的思想。具体来说,将二维矩阵每一行视为

一个柱状图的底部,并计算从当前行开始向上的柱子高度。这样,对于每一行,我们

都可以得到一个柱状图。

• 之后,我们就可以将这个柱状图传递给解决 084 题的方法,来找到这一行为底部时

的最大矩形面积。

• 最后,遍历矩阵的每一行,找到最大的面积。

当然了,还是存在一些其他情况的,比如说 柱子 从中间层断开了怎么办?

很简单,我们按照从上到下的层次来依次统计每一行的最大矩形面积,比如说第一行,第

一行+第二行,第一行+第二行+第三行,第一行+第二行+第三行+第四行。

看下边的橙色部分。

085.%E6%9C%80%E5%A4%A7%E7%9F%A9%E5%BD%A2-20231001075623.png

• 第一次,最大矩形面积为 1;

• 第二次,最大矩形面积为 3;

• 第三次,最大矩形面积为 6;

• 第四次,最大矩形面积为 4。

第四次的最大矩形面积比第三次小,是因为第四行出现了 0,导致比最高柱子小的左右两

侧的柱子都无法计算在内。

这样子的时间复杂度为$ O(nm) $,实际上是对每行都做了一次 084.柱状图中最大的矩

形。来看题解。

class Solution {

// 主函数:寻找最大矩形

public int maximalRectangle(char[][] matrix) {

// 判断空矩阵情况

if(matrix.length == 0) return 0;

// 创建高度数组,大小等于矩阵的列数

int[] height = new int[matrix[0].length];

int res = 0; // 最大矩形面积

// 遍历矩阵的每一行

for (char[] chars : matrix) {

// 更新当前行的高度

for (int col = 0; col < chars.length; col++) {

// 如果当前位置为'1',则累加高度

if (chars[col] == '1')

height[col]++;

else // 否则,重置高度为 0

height[col] = 0;

}

// 对于每一行,计算最大的矩形面积,并更新 res

res = Math.max(res, largestRectangleArea(height));

}

return res; // 返回最大矩形面积

}

// 辅助函数:计算柱状图中最大的矩形面积

public int largestRectangleArea(int[] heights) {

Stack<Integer> s = new Stack<>(); // 单调递增栈

int[] lefLower = new int[heights.length]; // 存储左边第一个小于当前高度的索引

int[] rigLower = new int[heights.length]; // 存储右边第一个小于当前高度的索引

Arrays.fill(rigLower,heights.length); // 初始化为右边界

// 遍历每个柱子

for(int i = 0;i < heights.length;i++) {

// 当栈不为空且当前柱子高度小于栈顶柱子的高度

while (!s.empty() && heights[s.peek()] > heights[i]) {

// 更新右边第一个小于栈顶柱子高度的索引

rigLower[s.pop()] = i;

}

// 更新左边第一个小于当前柱子高度的索引

lefLower[i] = s.empty() ? -1 : s.peek();

// 当前柱子索引入栈

s.push(i);

}

int res = 0; // 最大矩形面积

// 计算每个柱子的最大矩形面积

for(int i = 0;i < heights.length;i++) {

res = Math.max(res, (rigLower[i] - lefLower[i] - 1) * heights[i]);

}

return res; // 返回最大矩形面积

}

}

对于给定的输入 matrix:

[

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

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

["1","1","1","1","1"],

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

]

我们可以先计算每一行所形成的柱状图,然后使用前面描述的方法来求最大矩形面积。

具体操作如下:

1. 第一行:[1,0,1,0,0]

2. 第二行:[2,0,2,1,1]

3. 第三行:[3,1,3,2,2]

4. 第四行:[4,0,0,3,0]

接下来,对每一行都计算最大的矩形面积,然后选取这些面积中的最大值。

1. 对第一行:最大面积 = 1

2. 对第二行:最大面积 = 3 (由第二行第三列、第四列所形成的 2*1 的矩形)

3. 对第三行:最大面积 = 6 (由第三行第二列、第三列、第四列、第五列所形成的 2*3

的矩形)

4. 对第四行:最大面积 = 4 (由第四行第一列所形成的 4*1 的矩形)

因此,整个二维矩阵中的最大矩形面积是 6,所以输出为 6。

我们来看一下题解效率:

085.%E6%9C%80%E5%A4%A7%E7%9F%A9%E5%BD%A2-20231001075755.png

总结

本题其实也算是单调栈的运用,以及一个小小的思维拓展,把二维数组简化为一维数组。

这类题目还是需要多练习来强化自己的思维能力,从而快速发现破解点,将之前学过的单

调栈运用到本题中来解出答案。

力扣链接:https://leetcode.cn/problems/maximal-rectangle/

开通会员 本次下载免费

所有资料全部免费下载! 推荐用户付费下载获取返佣积分! 积分可以兑换商品!
一键复制 下载文档 联系客服