題目
Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area.
答案
類似Maximal Square,但是是錯(cuò)誤的dp解法
因?yàn)槟銢]法完全根據(jù)左邊,上邊,和左上角的三個(gè)cell的dp值來決定當(dāng)前cell的dp值
class Solution {
public int maximalRectangle(char[][] matrix) {
if(matrix.length == 0) return 0;
int rows = matrix.length, cols = matrix[0].length;
int[][][][] dp = new int[rows][cols][3][2];
int max_area = 0;
// base case dp[0][0]
if(matrix[0][0] == '1') {
for(int i = 0; i < 3; i++) {
int w = 1, h = 1;
dp[0][0][i][0] = w;
dp[0][0][i][1] = h;
max_area = Math.max(max_area, w * h);
}
}
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
// Skip base case
if(i == 0 && j == 0) continue;
// Skip '0' case
if(matrix[i][j] == '0') continue;
// Choice 0
int w = 1;
int h = 1 + ((i > 0) ? dp[i - 1][j][0][0] : 0);
dp[i][j][0][1] = w;
dp[i][j][0][0] = h;
max_area = Math.max(max_area, w * h);
// Choice 1
w = 1 + ((j > 0) ? dp[i][j - 1][1][1] : 0);
h = 1;
dp[i][j][1][1] = w;
dp[i][j][1][0] = h;
max_area = Math.max(max_area, w * h);
// Choice 2
w = 1 + ((i > 0 && j > 0) ? Math.min(dp[i - 1][j - 1][2][1], dp[i][j - 1][1][1]) : 0);
h = 1 + ((i > 0 && j > 0) ? Math.min(dp[i - 1][j - 1][2][0], dp[i - 1][j][0][0]) : 0);
dp[i][j][2][1] = w;
dp[i][j][2][0] = h;
max_area = Math.max(max_area, w * h);
}
}
return max_area;
}
}
正確答案
從這個(gè)題學(xué)會(huì)了:
有時(shí)候dp題,你并不能直接找到recurrence用以直接計(jì)算答案
但是你可以找到相關(guān)的其他變量x來計(jì)算recurrence,然后再用x來計(jì)算你所需的答案
class Solution {
public int maximalRectangle(char[][] matrix) {
if(matrix.length == 0) return 0;
int rows = matrix.length, cols = matrix[0].length, max_area = 0;
// dp[i][j] records how many consecutive 1's from left to grid[i][j]
int[][] dp_horz = new int[rows][cols];
for(int i = 0; i < rows; i++)
if(matrix[i][0] == '1') dp_horz[i][0] = 1;
for(int i = 0; i < rows; i++) {
for(int j = 1; j < cols; j++) {
if(matrix[i][j] == '0') continue;
dp_horz[i][j] = dp_horz[i][j - 1] + 1;
}
}
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
if(matrix[i][j] == '0') continue;
// How many consecutive 1's to the left of matrix[i][j]
int left1s = dp_horz[i][j];
// Iterate up
int min_w = left1s;
for(int k = i; k >= 0; k--) {
int h = i - k + 1;
int w = dp_horz[k][j];
if(w < min_w) min_w = w;
int area = h * min_w;
max_area = Math.max(max_area, area);
}
}
}
return max_area;
}
}