import java.util.*;
/**
* NC237 最大矩形
* @author d3y1
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param matrix int整型二维数组
* @return int整型
*/
public int maximalRectangle (int[][] matrix) {
return solution(matrix);
}
/**
* 动态规划 + 单调栈
*
* heights[i][j]表示以第i行为底的矩形图的第j列的高度
*
* { 0 , matrix[i-1][j-1] == 0
* heights[i][j] = {
* { heights[i-1][j] + 1 , matrix[i-1][j-1] == 1
*
*
* matrix
* i\j 1 2 3 4 5
* 1 1 0 1 0 0
* 2 1 1 1 1 0
* 3 1 1 1 1 1
* 4 1 0 0 1 0
*
* heights[i][j]
* i\j 1 2 3 4 5
* 1 1 0 1 0 0
* 2 2 1 2 1 0
* 3 3 2 3 2 1
* 4 4 0 0 3 0
*
* @param matrix
* @return
*/
private int solution(int[][] matrix){
int n = matrix.length;
int m = matrix[0].length;
int[][] heights = new int[n+1][m+1];
// 以第i行为底的矩形图的第j列的高度
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
if(matrix[i-1][j-1] == 1){
heights[i][j] = heights[i-1][j] + 1;
}
}
}
Stack<Integer> leftStack;
Stack<Integer> rightStack;
HashMap<Integer, Integer> leftMap;
HashMap<Integer, Integer> rightMap;
int area = 0;
// 分别计算以各行为底的矩形图
for(int i=1; i<=n; i++){
leftStack = new Stack<>();
rightStack = new Stack<>();
leftMap = new HashMap<>();
rightMap = new HashMap<>();
int height;
int index;
// 单调栈
for(int j=1; j<=m; j++){
height = heights[i][j];
// 单调增 从左往右 查找左边第一个小于当前元素的索引 0-左边界(表示未找到)
while(!leftStack.isEmpty() && height<=heights[i][leftStack.peek()]){
leftStack.pop();
}
index = leftStack.isEmpty()?0:leftStack.peek();
leftMap.put(j, index);
leftStack.push(j);
}
// 单调栈
for(int j=m; j>0; j--){
height = heights[i][j];
// 单调增 从右往左 查找右边第一个小于当前元素的索引 (m+1)-右边界(表示未找到)
while(!rightStack.isEmpty() && height<=heights[i][rightStack.peek()]){
rightStack.pop();
}
index = rightStack.isEmpty()?m+1:rightStack.peek();
rightMap.put(j, index);
rightStack.push(j);
}
// 计算当前矩形图 最大矩形面积
for(int j=1; j<=m; j++){
area = Math.max(area, heights[i][j]*(rightMap.get(j)-leftMap.get(j)-1));
}
}
return area;
}
}