Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and return its area.
题意:给出一个矩形,里面填充'0'和'1',找出完全由'1'组成的最大子矩形的面积。
分析:我是用dp做这道题的。用row[i][j]和col[i][j]分别记录以点(i,j)为右下角的全1子矩形的行数和列数。用right[i][j]和down[i][j]记录以(i,j)为结尾的从左到右连续1个数、从上到下连续1个数。
依次遍历每个点(i,j),考虑点(i-1,j)和(i,j-1)。
对于点(i-1,j),考虑(row[i-1][j]+1)*col[i-1][j]是否小于单行连续1个数right[i][j],若小于,记录以(i,j)为右下角的最大矩形为这个单行连1;否则,记录为(i-1,j)对应矩形加当前行,列数为min(col[i-1][j],right[i][j])。
对于点(i-1,j),考虑row[i][j-1]*(col[i][j-1]+1)是否小于单列连续1个数down[i][j],若小于,记录以(i,j)为右下角的最大矩形为这个单列连1;否则,记录为(i,j-1)对应矩形加当前列,行数为min(row[i][j-1],down[i][j])。
选上述两个结果的较大矩形,作为(i,j)的结果。
记录所有点中的最大矩形面积,即为结果。
代码:
class Solution { public: int maximalRectangle(vector<vector<char> > &matrix) { int n = matrix.size(); if(n==0) return 0; int m = matrix[0].size(); if(m==0) return 0; int **row = new int*[n+1]; int **col = new int*[n+1]; int **right = new int*[n+1]; int **down = new int*[n+1]; for(int i=0; i<=n; i++) { row[i] = new int[m+1]; col[i] = new int[m+1]; right[i] = new int[m+1]; down[i] = new int[m+1]; memset(row[i],0,sizeof(int)*(m+1)); memset(col[i],0,sizeof(int)*(m+1)); memset(right[i],0,sizeof(int)*(m+1)); memset(down[i],0,sizeof(int)*(m+1)); } for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { if(matrix[i][j]=='0') right[i+1][j+1]=0; else right[i+1][j+1]=right[i+1][j]+1; } } for(int i=0; i<m; i++) { for(int j=0; j<n; j++) { if(matrix[j][i]=='0') down[j+1][i+1]=0; else down[j+1][i+1]=down[j][i+1]+1; } } int ans = 0; for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { if(matrix[i-1][j-1]=='1') { row[i][j]=1; col[i][j]=1; int r1,c1,r2,c2; if(right[i][j]>(row[i-1][j]+1)*col[i-1][j]) { r1 = 1; c1 = right[i][j]; } else { r1 = row[i-1][j]+1; c1 = min(col[i-1][j],right[i][j]); } if(down[i][j]>row[i][j-1]*(col[i][j-1]+1)) { r2 = down[i][j]; c2 = 1; } else { r2 = min(row[i][j-1],down[i][j]); c2 = col[i][j-1]+1; } if(r1*c1>r2*c2) { row[i][j] = r1; col[i][j] = c1; } else { row[i][j] = r2; col[i][j] = c2; } if(row[i][j]*col[i][j]>ans) ans = row[i][j]*col[i][j]; } } } return ans; } };