题目信息:
代码思路:
其实是逐行考虑,每一行的数组看成一个柱状图,求这个柱状图能画出来的最大矩形面积。
然后第二行会考虑上一行的数值,如果是连续的1,则下一行的柱子高度加1,同样计算第二行的最大矩形面积。
...
最后选择最大的矩形的面积即可。
代码:
package com.me.leetcode;
import java.util.Stack;
public class MaxRectangle {
public static void main(String[] args) {
char[][] matrix = new char[][] {
{'1','0','1','1','1'},
{'1','1','1','0','1'},
{'1','1','1','1','1'},
{'1','1','1','1','1'}
};
// char[][] matrix = new char[][] {
// {'0','1'},
// {'1','0'}
// };
System.out.println(maximalRectangle(matrix));
}
/**
* 求二维数组中的最大矩形面积
* @param matrix
* @return
*/
public static int maximalRectangle(char[][] matrix) {
if (matrix.length == 0) {
return 0;
}
int [] hights = new int[matrix[0].length];
int maxSize = 0;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
// 如果本行是0,则该行的柱子高度是0,否则就是上一行的柱子高度加1
hights[j] = matrix[i][j] == '0'? 0:hights[j] + 1;
}
// 逐行求最大矩形,并取最大值
maxSize = Math.max(getMaxRec(hights), maxSize);
}
return maxSize;
}
/**
* 求柱状图中能裁出来的最大矩形面积
* @param hights
* @return
*/
public static int getMaxRec(int[] hights) {
// 用来存放对应柱子的左边第一个最小的柱子的下标和右边第一个最小 的柱子的下标
int[][] indexs = new int[hights.length][2];
// 采用单调栈来做,可以降低代码时间复杂度
Stack<Integer> stack = new Stack<Integer>();
// 遍历每个柱子
for (int i = 0; i < hights.length; i++) {
// 初始状态时,把每个柱子的左边最小柱子置为-1,右边最小的柱子置为hights.length
indexs[i][0] = -1;
indexs[i][1] = hights.length;
if (stack.isEmpty()) {
// 空栈,压入下标
stack.push(i);
} else {
// 为了让栈中的下标指示的元素保持单调递增, 需要把不满足的下表出栈
while (!stack.isEmpty() && hights[stack.lastElement()] > hights[i]) {
// 元素出栈时,出栈元素左边第一个比它小的元素即是当前i代表的元素。
int index = stack.lastElement();
indexs[index][1] = i;
stack.pop();
}
if (!stack.isEmpty()) {
// 压下表进栈时,说明此时栈顶的元素是当前i元素左边第一个最小的数
indexs[i][0] = stack.lastElement();
}
stack.push(i);
}
}
// 把栈中的元素出栈
// while (!stack.isEmpty()) {
// // 此时栈中的元素右边最小的元素是没有的,这个循环其实是没必要的
// indexs[stack.lastElement()][1] = hights.length;
// stack.pop();
// }
int maxSum = 0;
for (int i = 0; i < indexs.length; i++) {
maxSum = Math.max(maxSum, (indexs[i][1] - indexs[i][0] - 1) * hights[i]);
}
return maxSum;
}
}
Q.E.D.