假设数组大小为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; } }