【leetcode高频问题-动态规划】85.(Hard) Maximal Rectangle

解题思路

假设数组大小为m*n,数据如下:
在这里插入图片描述
过程是:遍历整个数组,遍历的顺序是从上到下,一排一排的遍历。
每遍历一排都要更新三个数组的数据,这三个数组分别是height[n], left[n], right[n]
每遍历一排都通过更新后的height, left, right中的数据计算一遍是否存在更大的矩阵

三个数组的含义如下:
height[j]:遍历到某一行时,该行上连续的1的个数
例如对于第2行(1 1 1 1 1)的数据来说,height遍历后的结果是3 1 3 2 2
在这里插入图片描述
所有的遍历结果如下:
在这里插入图片描述

left[j] :遍历到某一行第j个位置时,高度高于height[j]的最左边的位置。
例如对于(2,3)这个位置的1来说,left[j]是2,即该行第三个1所在的位置。
因为对(2,3)这个位置的1来说,高度是2,height[3]=2
令2是矩形的高度的话,这个矩形最多只能拓展到第三个1(打勾的那个1)的位置,
不能拓展到第一个1所在的位置。
在这里插入图片描述

right[j]:以此类推,right[j]是遍历到某一行第j个位置时,高度高于height[j]的最左边的位置。

全部遍历一遍的话,对于每个坐标的矩形统计出来是这个样子的:
第0排:
在这里插入图片描述
第一排:
第一排总共有4个1,第一个和第二个1代表的矩形是下面这样子:
在这里插入图片描述
第一排的第三个和第四个1圈出来的矩形是同一个:
在这里插入图片描述
第二排:
第一个1圈出来的矩形:
在这里插入图片描述
第二个1圈出来的矩形:
在这里插入图片描述
第三、四、五个1圈出来的矩形都是一样的:
在这里插入图片描述
第三排:
在这里插入图片描述


总体来说,如果一个位置是1,先用一个矩形把这个1框起来;
然后把这个矩形向上拉,看这个矩形向上能够到多高;
然后令这个矩形的高度不变,将这个矩形向两边拉伸,看向两边能拉伸到多远。

例如对于夏明的这个1:
在这里插入图片描述
先将矩形框向上拉:
在这里插入图片描述
然后保持这个矩形框的高度不变,将这个矩形向两边拉,最终确定的矩形就是下面这个样子:
在这里插入图片描述

代码思路

写代码的时候,一排一排地遍历每一行的数字作为外循环;
然后对于每一行,首先从左到右更新height和left数组;
然后从右到左遍历right数组
最后每次更新完height, left, right都计算一下当前行是否可以产生新的更大的矩形

代码如下

class Solution {
    public int maximalRectangle(char[][] matrix) {
    	if(matrix==null||matrix.length==0||matrix[0]==null||matrix[0].length==0)	return 0;
    	int m=matrix.length;
    	int n=matrix[0].length;
    	
    	int[] left=new int[n], right =new int[n], height=new int[n];
    	Arrays.fill(right, n);
    	int lb,rb, maxRec=0;
    	
    	for(int i=0;i<m;i++) {
    		lb=0;rb=n;
    		
			// update height
			for(int j=0;j<n;j++) {
				if(matrix[i][j]!='0')	height[j]++;
				else	height[j]=0;
			}
			
			// update left
			for(int j=0;j<n;j++) {
				if(matrix[i][j]!='0') {
					left[j]=Math.max(left[j], lb);
				}else {
					left[j]=0;
					lb=j+1;
				}
			}
			
			// update right
			for(int j=n-1;j>=0;j--) {
				if(matrix[i][j]!='0') {
					right[j]=Math.min(right[j], rb);
				}else {
					right[j]=n;
					rb=j;
				}
			}
			
			// calculate max rectangle
			int curRec=0;
			for(int j=0;j<n;j++) {
				curRec=(right[j]-left[j])*height[j];
				maxRec=curRec>maxRec?curRec:maxRec;
			}
    	}
    	return maxRec;
    }
    
 
    
}
运行结果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值