LeetCode085 Maximal Rectangle(Not fully understand)
Given a 2D binary matrix filled with 0’s and 1’s, find the largest rectangle containing only 1’s and return its area.
example:
Input:
[
[“1”,“0”,“1”,“0”,“0”],
[“1”,“0”,“1”,“1”,“1”],
[“1”,“1”,“1”,“1”,“1”],
[“1”,“0”,“0”,“1”,“0”]
]
Output: 6
simple dp problem. but the results of following code is not right, and I don’t understand why.
class Solution {
public int maximalRectangle(char[][] matrix) {
if (matrix == null || matrix.length == 0) {
return 0;
}
int m = matrix.length;
int n = matrix[0].length;
int[][] maxLeft = new int[m][n]; //maxLeft[i] is the longest left consective number of 1s contains current place
int[][] maxUp = new int[m][n]; //maxUp[i] is the longest up consective number of 1s contains current place
//so that why the global maximal of maxLeft[i][j]*maxUp[i][j] will be the final results
if (matrix[0][0] == '1') {
maxLeft[0][0] = 1;
maxUp[0][0] = 1;
} else {
maxLeft[0][0] = 0;
maxUp[0][0] = 0;
}
for (int i = 1; i<n; i++) {
if (matrix[0][i] == '1') {
maxLeft[0][i] = maxLeft[0][i-1] + 1;
} else {
maxLeft[0][i] = 0;
}
}
for (int i = 1; i<m; i++) {
if (matrix[i][0] == '1') {
maxUp[i][0] = maxUp[i-1][0] + 1;
} else {
maxUp[i][0] = 0;
}
}
for (int i = 1; i<m; i++) {
for (int j = 1; j<n; j++) {
if (matrix[i][j] == '1') {
maxLeft[i][j] = maxLeft[i][j-1] + 1;
maxUp[i][j] = maxUp[i-1][j] + 1;
} else {
maxLeft[i][j] = 0;
maxUp[i][j] = 0;
}
}
}
int res = 0;
for (int i = 0; i < m; i++){
for (int j = 0; j<n; j++) {
res = Math.max(res, maxUp[i][j] * maxLeft[i][j]);
}
}
return res;
}
}
Now, I know why previous code is not right! This entire code is totally wrong!! I only considered the upper and left, but what we really need, is a rectangle filled with 1s.
so situations like:
000100
000100
011100
000000
my code will get the result of 9, but the correct result is 1.
so I rewrite my code, it is still not working:
class Solution {
public int maximalRectangle(char[][] matrix) {
if (matrix == null || matrix.length == 0) {
return 0;
}
int m = matrix.length;
int n = matrix[0].length;
int[][] maxLeft = new int[m][n]; //maxLeft[i] is the longest left consective number of 1s contains current place
int[][] maxUp = new int[m][n]; //maxUp[i] is the longest up consective number of 1s contains current place
//so that why the global maximal of maxLeft[i][j]*maxUp[i][j] will be the final results
int[][] dp = new int[m][n];
int res = 0;
if (matrix[0][0] == '1') {
maxLeft[0][0] = 1;
maxUp[0][0] = 1;
dp[0][0] = 1;
res = 1;
} else {
maxLeft[0][0] = 0;
maxUp[0][0] = 0;
dp[0][0] = 0;
}
for (int i = 1; i<n; i++) {
if (matrix[0][i] == '1') {
maxLeft[0][i] = maxLeft[0][i-1] + 1;
} else {
maxLeft[0][i] = 0;
}
}
for (int i = 1; i<m; i++) {
if (matrix[i][0] == '1') {
maxUp[i][0] = maxUp[i-1][0] + 1;
} else {
maxUp[i][0] = 0;
}
}
for (int i = 1; i<m; i++) {
for (int j = 1; j<n; j++) {
if (matrix[i][j] == '1') {
maxLeft[i][j] = maxLeft[i][j-1] + 1;
maxUp[i][j] = maxUp[i-1][j] + 1;
} else {
maxLeft[i][j] = 0;
maxUp[i][j] = 0;
}
}
}
for (int i = 1; i < m; i++) {
dp[i][0] = maxUp[i][0] * 1;
res = Math.max(res, dp[i][0]);
}
for (int i = 1; i < n; i++) {
dp[0][i] = maxLeft[0][i] * 1;
res = Math.max(res, dp[0][i]);
}
for (int i = 1; i < m; i++){
for (int j = 1; j<n; j++) {
if (matrix[i][j] == '1'){
if (dp[i-1][j-1] == 0) {
dp[i][j] = Math.max(maxUp[i][j], maxLeft[i][j]);
} else {
dp[i][j] = (Math.min(maxUp[i][j] - 1, maxUp[i-1][j-1]) + 1) * (Math.min(maxLeft[i][j] - 1, maxLeft[i-1][j-1]) + 1);
}
res = Math.max(res, dp[i][j]);
}
}
}
return res;
}
}
the following code is accepted, but I’m not fully understand. and the person who thought of this solution says he is inspried by other problems call maximal rectangle in histogram. but I don’t think they are so similiar, at least we only use a ple stack in this solution.
class Solution {
public int maximalRectangle(char[][] matrix) {
if (matrix == null || matrix.length == 0) return 0;
int n = matrix[0].length;
int[] height = new int[n + 1];//只用了一个height数组
height[n] = 0;
int res = 0;
for (int row = 0; row < matrix.length; row++) {//row by row
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < n + 1; i++) {//
if (i < n) { //如果i在matrix里面作为列数是合法的
if (matrix[row][i] == '1') {
height[i]++; //这里的height[i]就跟俄罗斯方块一样 代表当前此列连续积累的高度
} else height[i] = 0;//构建height数组的方式跟上个方法一样
}
while (!stack.isEmpty() && height[i] < height[stack.peek()]) { //we maintain an element increasing stack, which is the ple of current index
int cur = height[stack.pop()] * (stack.isEmpty() ? i : (i - stack.peek() - 1)); //can't fully understand this statement. because, as we known, stack.pop() is the largest in stack, and it's peek() is the second largest. so why do I have to use height[stack.pop()] * (stack.isEmpty() ? i : (i - stack.peek() - 1))?
res = Math.max(res, cur);
}
stack.push(i);
}
}
return res;
}
}
and there is a dp solution for this problem:
this solution is much alike the solution in maximal rectangle in histogram.
- 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]; which is similar to a decrease stack
- right[i] record the right most index j which satifies that for any index k from i to j, height[k] >= height[i]; which is similiar to a decrease stack
- by understanding the definition, we can easily figure out we need to update maxArea with value (height[i] * (right[i] - left[i] + 1));
//based on this, we have following code. the code is written by myself, which is exactly the same as the solution provided by others, but it just couldn’t be accepted! WTF?
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 res = 0;
int[] left = new int[n];
int[] right = new int[n];
int[] height = new int[n];
Arrays.fill(right, n - 1); //why we have to initialize right will n-1??????????
for (int i = 0; i < m; i++) { //row by row
int rB = n - 1;
for (int j = n - 1; j >= 0; j--) {
if (matrix[i][j] == '1') {
right[j] = Math.min(right[j], rB); //due to we need to find the closest right index
} else { //if the current position has value of 0, which means
right[j] = n - 1; //because we have already initialize right with n-1, so we don't necessaily need to write this
rB = j - 1;
}
}
int lB = 0;
for (int j = 0; j < n; j++) {
if (matrix[i][j] == '1') {
left[j] = Math.max(left[i], lB);
height[j]++;
res = Math.max(res, height[j] * (right[j] - left[j] + 1));
} else {
left[j] = 0; //not necessary
lB = j + 1;
height[j] = 0;
}
}
}
return res;
}
}

浙公网安备 33010602011771号