「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」
前言
力扣第八十五题 最大矩形
如下所示:
给定一个仅包含 0
和 1
、大小为 rows x cols
的二维二进制矩阵,找出只包含 1
的最大矩形,并返回其面积。
示例 1:
输入: matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出: 6
解释: 最大矩形如上图所示。
一、思路
这一题我刚开始也是看了很久,都没有弄明白要怎么写。后来看了一下力扣的题解,才明白这一题和昨天的 力扣第八十四题-柱状图中最大的矩形
思路是一样的,不过要绕一点而已。
我们知道在一个二维矩阵中,如果要画一个矩形。这个矩形的有边界一定会落在二维矩阵的某一列上。
假设要你画一个矩形:矩形的右边在第三列上,求它的最大面积。如下图所示:
你会怎么做呢?其实很简单我们可以先找到这一列向左有多个 1
,这就是矩形的高。这个题目就变成了在这个柱状图中,找到最大的矩形面积了。题目示意如下所示:
综上所述,这一题的大致步骤如下所示:
- 遍历整个二维矩阵,每个点
left[i][j]
左边连续的1
(如果自身为1
长度也需要加一) - 我们取出每一列
left[][j]
,将每一列都看做柱状图
- 通过
单调栈
找到柱状图中最大的矩形面积 - 最终,返回最大的矩形面积即可
这一题我觉得最难的地方就是找到矩阵中的每一个点左边连续
1
的个数,再将得到的结果left[][]
中的每一列看做一个柱状图。
至于如何使用单调栈
在柱状图中找到最大的矩形面积,可以看我写的上一篇博客,里面有详细的图解算法。
二、实现
实现代码
实现代码与思路中保持一致
public int maximalRectangle(char[][] matrix) {
int row = matrix.length;
if (row == 0) {
return 0;
}
int col = matrix[0].length;
int[][] left = new int[row][col];
// 找到每个点左边有多少个连续1 (包括自己)
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (matrix[i][j] == '1') {
// 如果是第一列的1,则结果为1
left[i][j] = j == 0 ? 1 : left[i][j - 1] + 1;
}
}
}
int ret = 0;
for (int j = 0; j < col; j++) { // 对于每一列,使用基于柱状图的方法
int[] bottom = new int[row]; // 下边界
int[] top = new int[row]; // 上边界
int topIndex = 0; // 记录上一次更新上边界的位置
Deque<Integer> stack = new LinkedList<>();
for (int i = 0; i < row; i++) {
// 只要栈中的下标对应的高度比当前的高度高,就出栈。保证栈顶为最靠近且值小于的元素
while (!stack.isEmpty() && left[stack.peek()][j] >= left[i][j]) {
stack.pop();
}
bottom[i] = stack.isEmpty() ? -1 : stack.peek();
stack.push(i);
}
stack.clear();
for (int i = row - 1; i >= 0; i--) {
while (!stack.isEmpty() && left[stack.peek()][j] >= left[i][j]) {
stack.pop();
}
top[i] = stack.isEmpty() ? row : stack.peek();
stack.push(i);
}
// 根据上下边界,求出以 `left[i][j]` 作为高的面积
for (int i = 0; i < row; i++) {
ret = Math.max(ret, (top[i] - bottom[i] - 1) * left[i][j]);
}
}
return ret;
}
测试代码
public static void main(String[] args) {
char[][] matrix = {{'1','0','1','0','0'},{'1','0','1','1','1'},{'1','1','1','1','1'},{'1','0','0','1','0'}};
new Number85().maximalRectangle(matrix);
}
结果
三、总结
感谢看到最后,非常荣幸能够帮助到你~♥
如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~