题目
给定一个由 0 和 1 组成的矩阵 matrix ,找出只包含 1 的最大矩形,并返回其面积。
注意:此题 matrix 输入格式为一维 01 字符串数组。
示例
示例 1:
输入:matrix = ["10100","10111","11111","10010"]
输出:6
解释:最大矩形如上图所示。
示例 2:
输入:matrix = []
输出:0
示例 3:
输入:matrix = ["0"]
输出:0
示例 4:
输入:matrix = ["1"]
输出:1
示例 5:
输入:matrix = ["00"]
输出:0
方法
单调栈
class Solution {
public int maximalRectangle(String[] matrix) {
int area = 0;
if(matrix.length == 0 || matrix[0].length() == 0) return 0;
int col = matrix[0].length();
int row = matrix.length;
int[] tool = new int[col];
for(String rownumber: matrix){
for(int j=0;j<col;j++){
if(rownumber.charAt(j) == '1'){
tool[j]++;
}else{
tool[j] = 0;
}
}
area = Math.max(area, countArea(tool));
}
return area;
}
public int countArea(int[] heights){
Deque<Integer> stack = new LinkedList<>();
stack.push(-1);
int maxArea = 0;
for (int i = 0; i < heights.length; i++) {
while (stack.peek() != -1 && heights[stack.peek()] >= heights[i]) {
int height = heights[stack.pop()];
int width = i - stack.peek() - 1;
maxArea = Math.max(height * width, maxArea);
}
stack.push(i);
}
while (stack.peek() != -1) {
int height = heights[stack.pop()];
int width = heights.length - stack.peek() - 1;
maxArea = Math.max(height * width, maxArea);
}
return maxArea;
}
}
1 从矩阵的第一行向下逐行遍历,这样就可以将矩阵看作以列方向为横坐标的一个直方图,求矩阵的最大面积,就变为求直方图内的最大矩形面积。
2 遍历过程中使用tool数组,计算当前坐标上的直方图高度,如果当前对应矩阵位置是1,就累加到tool[i]上,如果是0说明这个矩形断开,直接将tool[i]归零。
3 求直方图最大矩形的问题,使用单调栈解决。
先压入-1作为左边界,只要比栈顶小就压入,压入的值是下标,取出来对比是按照下标对应的高度。一旦栈顶高度比当前遍历的高度高,则将栈顶弹出,计算出 栈顶对应高度 * 左右高度比他低的边界值 = 当前面积 ,用area全程记录最大值就是直方图内的最大矩形面积。
4 重点是
1:将矩阵最大面积,转化为按行求累积的直方图内最大矩形面积。
2:求直方图内最大矩形面积时,存入单调栈的是下标,但是比较的时候用的是下标对应的高度值
3:因为直方图内所有的矩形都是以某个下标的高度为基准向两边比他高度低的下标处为界限生成的,因此使用单调栈,每当到达一个边界就循环弹出栈内的可以作为高度基准的元素,然后记录面积值,保留最大的。