You can maintain a row length of Integer array H recorded its height of '1's, and scan and update row by row to find out the largest rectangle of each row.
For each row, if matrix[row][i] == '1'. H[i] +=1, or reset the H[i] to zero.
and accroding the algorithm of [Largest Rectangle in Histogram], to update the maximum area.
classSolution {publicintmaximalRectangle(char[][] matrix) {int rLen =matrix.length, cLen = rLen ==0?0: matrix[0].length, max =0;int[] h =newint[cLen+1];for (int row =0; row < rLen; row++) {Stack<Integer> s =newStack<Integer>();s.push(-1);for (int i =0; i <= cLen ;i++) {if(i < cLen && matrix[row][i] =='1') h[i] +=1;else h[i] =0;while(s.peek() !=-1&& h[i] < h[s.peek()]) {int height = h[s.pop()];int width = i -s.peek() -1; max =Math.max(max, height * width); }s.push(i); } }return max; }}
The DP solution proceeds row by row, starting from the first row. Let the maximal rectangle area at row i and column j be computed by [right(i,j) - left(i,j)]*height(i,j).
All the 3 variables left, right, and height can be determined by the information from previous row, and also information from the current row. So it can be regarded as a DP solution. The transition equations are:
left(i,j) = max(left(i-1,j), cur_left), cur_left can be determined from the current row
right(i,j) = min(right(i-1,j), cur_right), cur_right can be determined from the current row
height(i,j) = height(i-1,j) + 1, if matrix[i][j]=='1';
/* we start from the first row, and move downward; * height[i] record the current number of countinous '1' in column i; * left[i] record the left most index j which satisfies that for any index k from j to i, height[k] >= height[i]; * right[i] record the right most index j which satifies that for any index k from i to j, height[k] >= height[i]; * by understanding the definition, we can easily figure out we need to update maxArea with value (height[i] * (right[i] - left[i] + 1));
* * Then the question is how to update the array of height, left, and right * ================================= * for updating height, it is easy * for (int j = 0; j < n; j++) { * if (matrix[i][j] == '1') height[j]++; * else height[j] = 0; * } * ============================================================================= * It is a little bit tricky for initializing and updating left and right array * for initialization: * we know initially, height array contains all 0, so according to the definition of left and right array, left array should contains all 0, and right array should contain all n - 1
* for updating left and right, it is kind of tricky to understand... * ============================================================== * Here is the code for updating left array, we scan from left to right * int lB = 0; //lB is indicating the left boundry for the current row of the matrix (for cells with char "1"), not the height array...
* for (int j = 0; j < n; j++) { * if (matrix[i][j] == '1') { * left[j] = Math.max(left[j], lB); // this means the current boundry should satisfy two conditions: within the boundry of the previous height array, and within the boundry of the current row...
* } else { * left[j] = 0; // when matrix[i][j] = 0, height[j] will get update to 0, so left[j] becomes 0, since all height in between 0 - j satisfies the condition of height[k] >= height[j];
* lB = j + 1; //and since current position is '0', so the left most boundry for next "1" cell is at least j + 1;
* } * } * ============================================================== * the idea for updating the right boundary is similar, we just need to iterate from right to left * int rB = n - 1; * for (int j = n - 1; j >= 0; j--) { * if (matrix[i][j] == '1') { * right[j] = Math.min(right[j], rB); * } else { * right[j] = n - 1; * rB = j - 1; * } */classSolution {publicintmaximalRectangle(char[][] matrix) {if (matrix ==null||matrix.length==0|| matrix[0] ==null|| matrix[0].length==0) return0;int m =matrix.length, n = matrix[0].length, maxArea =0;int[] left =newint[n];int[] right =newint[n];int[] height =newint[n];Arrays.fill(right, n -1);for (int i =0; i < m; i++) {int rB = n -1;for (int j = n -1; j >=0; j--) {if (matrix[i][j] =='1') { right[j] =Math.min(right[j], rB); } else { right[j] = n -1; rB = j -1; } }int lB =0;for (int j =0; j < n; j++) {if (matrix[i][j] =='1') { left[j] =Math.max(left[j], lB); height[j]++; maxArea =Math.max(maxArea, height[j] * (right[j] - left[j] +1)); } else { height[j] =0; left[j] =0; lB = j +1; } } }return maxArea; }}