问题描述:给定一个矩形区域,每个位置上都是1或0,求该矩阵中每个位置上都是1的最大子矩形区域中 1 的个数。
例题:
解题的思路:
先看矩形的第一行“1 0 1 1”,最大子矩形是“1 1”,1的个数是2;
再看1,2两行 “1 0 1 1” 最大子矩形是“1 1”,1的个数是4;最后看1,2,3行,最
1 1 1 1 1 1
大子矩形是“1 1 1”,1的个数是6。 解题完毕。反观解题的整个过程,找最大子矩
1 1 1
形,然后数1的个数,怎么数呢?矩形的长 x 宽,其实我们是在算矩形的面积!所以本题使用一个一维数组 height [ ]来记录子矩形中每一列的1的高度,记录的原则是,如果遇到1,高度+1,如果遇到0,高度归零。例题的height[ ]={3,2,3,0},见图1。
![图1](https://img-blog.csdnimg.cn/20191015145124665.PNG) 统计完高度后,根据height[ ]数组计算矩形的面积,这里使用一个内部元素递增的栈来实现,在元素出栈是计算矩形面积。 代码如下:
public class MaxSubRectangle {
public static int maxRecSize(int[][] num) {
if(num == null || num.length==0 || num[0].length==0)
return 0;
int maxArea = 0; //记录最大的面积
int height[] = new int[num[0].length]; //记录每一列中“1”的高度
for(int i=0; i<num.length; i++){
for(int j=0; j<num[0].length; j++)
height[j] = num[i][j]==0 ? 0 : height[j] + 1;
maxArea = calculateMaxArea(height);
}
return maxArea;
}
public static int calculateMaxArea(int[] height) {
if(height == null || height.length == 0){
return 0;
}
int maxArea=0;
Stack<Integer> incrementStack = new Stack<>(); //维持栈内元素递增的栈
for(int i=0; i < height.length; i++){
while(!incrementStack.isEmpty() && height[i] <= height[incrementStack.peek()]) { //开始计算 i 列之前的矩形面积
//index :矩形右边的宽所在的列的索引(矩形有两条宽,左边一条,右边一条)
int index = toBiggerStack.pop();
//incrementStack栈顶的元素的索引
int leftNumIndex= incrementStack.isEmpty() ? -1 : incrementStack.peek();
int curArea = (i-leftNumIndex-1) * height[index];
//i - leftNumIndex - 1代表矩形的长度(i 与leftNumIndex 之间有多少列,比如1和4之间有两列,2和3,4-1-1=2)
maxArea = Math.max(curArea, maxArea);
}
//height[i]比栈顶元素大,直接入栈顶
incrementStack.push(i);
}
//height[ ]数组中元素末尾部分一直递增的,栈中还有元素未能出栈的情况,做出栈处理,计算矩形面积。
while(!incrementStack.isEmpty()) {
int index = incrementStack.pop();
int leftNumIndex = incrementStack.isEmpty() ? -1 : incrementStack.peek();
int curArea = (height.length -leftNumIndex-1) * height[index];
maxArea = Math.max(curArea, maxArea);
}
return maxArea;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int rows = sc.nextInt();
int columns = sc.nextInt();
int num[][] = new int[rows][columns];
//手动输入矩形数组
for(int i=0; i<rows; i++){
for(int j=0; j<columns; j++){
num[i][j]=sc.nextInt();
}
}
int result = maxRecSize(num);
System.out.print(result);
}
}
以上就是最大子矩形的解法。