leetcode.85. 最大矩形
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/maximal-rectangle
题目描述
给定一个仅包含 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
解释:最大矩形如上图所示。
示例 2:
输入:matrix = []
输出:0
示例 3:
输入:matrix = [[“0”]]
输出:0
示例 4:
输入:matrix = [[“1”]]
输出:1
示例 5:
输入:matrix = [[“0”,“0”]]
输出:0
提示:
rows == matrix.length
cols == matrix[0].length
1 <= row, cols <= 200
matrix[i][j] 为 ‘0’ 或 ‘1’
单调栈加数组优化栈
解题思路:
我们以以第一行为基座,生成每一列的矩形大小,从上往下加,遇到1,就相加,遇到0 ,就说明矩形中断了,我们就让他变成0,
如图所示:
如图所示:以第一行为基座,最后生成类似下面这个图形,是不是就类似:leetcode84. 柱状图中最大的矩形
,遍历每一列的位置,以当前位置为最小值,查到能覆盖的最大范围,求出矩形的数据量.循环遍历后,就能求出最大值了.
这题也是单调栈的应用,
单调栈的流程:
以一个例子来说明:
单调栈分为单调递增栈和单调递减栈
11. 单调递增栈即栈内元素保持单调递增的栈
12. 同理单调递减栈即栈内元素保持单调递减的栈
操作规则(下面都以单调递增栈为例)
21. 如果新的元素比栈顶元素大,就入栈
22. 如果新的元素较小,那就一直把栈内元素弹出来,直到栈顶比新元素小
加入这样一个规则之后,会有什么效果
31. 栈内的元素是递增的
32. 当元素出栈时,说明这个新元素是出栈元素向后找第一个比其小的元素
举个例子,配合下图,现在索引在 6 ,栈里是 1 5 6 。
接下来新元素是 2 ,那么 6 需要出栈。
当 6 出栈时,右边 2 代表是 6 右边第一个比 6 小的元素。
当元素出栈后,说明新栈顶元素是出栈元素向前找第一个比其小的元素
当 6 出栈时,5 成为新的栈顶,那么 5 就是 6 左边第一个比 6 小的元素。
代码演示
/**
* 最大矩形面积
* @param matrix
* @return
*/
public int maximalRectangle(char[][] matrix) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0){
return 0;
}
int cL = matrix[0].length;
int maxArea = 0;
int[] height = new int[cL];
//以第一行为基座,求出每一列的矩形大小
for (int i = 0 ; i < matrix.length;i++){
for (int j = 0;j < cL;j++){
height[j] = matrix[i][j] == '0' ? 0 : height[j] + 1;
}
maxArea = Math.max(maxArea,maxRecFromBottom(height));
}
return maxArea;
}
/**
* 计算当前行时,最大的矩形面积,单调栈的方式求
* @param height
* @return
*/
public int maxRecFromBottom(int[]height){
int N = height.length;
//用数组来优化栈结构,常数时间会更好
int[]stack = new int[N];
//维护栈的实际长度
int stackSize = 0;
int maxArea = 0;
for (int i = 0; i < N;i++){
while(stackSize != 0 && height[stack[stackSize - 1]] >= height[i]){
int J = stack[--stackSize];
//左边界
int left = stackSize == 0 ? -1 : stack[stackSize - 1];
int area = (i - left - 1) * height[J];
maxArea = Math.max(maxArea,area);
}
stack[stackSize++] = i;
}
while (stackSize != 0 ){
int J = stack[--stackSize];
int left = stackSize == 0 ? -1 : stack[stackSize - 1];
int area = (N - left - 1) * height[J];
maxArea = Math.max(maxArea,area);
}
return maxArea;
}