来源,leetcode 每日一题 85. 最大矩形
例如:
输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出:6
解释:最大矩形如上图所示。
示例2:
输入:matrix = []
输出:0
示例3:
输入:matrix = [["0","0"]]
输出:0
解题思路
- 暴力方法:最原始地,我们可以列举每个可能的矩形。这可以通过遍历所有的(x1, y1) (x2, y2) 坐标,并以它们为对角顶点来完成。该方法过慢,不足以通过所有测试用例。
动态规划 - 使用柱状图的优化暴力方法:
- 遍历得到每个点的最大宽度
- 计算以每个点为右下角的矩形的最大面积。
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
int rows = matrix.size();
if (rows == 0) {
return 0;
}
int columns = matrix[0].size();
if (columns == 0) {
return 0;
}
vector<vector<int>> maxWidth(rows, vector<int>(columns));
for (int i = 0; i < rows; i++) {
if (matrix[i][0] == '1') {
maxWidth[i][0] = 1;
}
for (int j = 1; j < columns; j++) {
if (matrix[i][j] == '1') {
maxWidth[i][j] = maxWidth[i][j-1] + 1;
}
}
}
int max_area = 0;
for (int j = 0; j < columns; j++) {
for (int i = 0; i < rows; i++) {
if (maxWidth[i][j] == 0) {
continue;
}
int height = 1;
int width = maxWidth[i][j];
max_area = max(width * height, max_area);
for (int h = i + 1; h < rows; h++) {
if (maxWidth[h][j] != 0) {
height += 1;
width = min(maxWidth[h][j], width);
max_area = max(height*width, max_area);
} else {
break;
}
}
}
}
return max_area;
}
};
优化
class Solution {
public int maximalRectangle(char[][] matrix) {
if(matrix.length == 0) return 0;
int m = matrix.length;
int n = matrix[0].length;
int[] left = new int[n]; // initialize left as the leftmost boundary possible
int[] right = new int[n];
int[] height = new int[n];
Arrays.fill(right, n); // initialize right as the rightmost boundary possible
int maxarea = 0;
for(int i = 0; i < m; i++) {
int cur_left = 0, cur_right = n;
// update height
for(int j = 0; j < n; j++) {
if(matrix[i][j] == '1') height[j]++;
else height[j] = 0;
}
// update left
for(int j=0; j<n; j++) {
if(matrix[i][j]=='1') left[j]=Math.max(left[j],cur_left);
else {left[j]=0; cur_left=j+1;}
}
// update right
for(int j = n - 1; j >= 0; j--) {
if(matrix[i][j] == '1') right[j] = Math.min(right[j], cur_right);
else {right[j] = n; cur_right = j;}
}
// update area
for(int j = 0; j < n; j++) {
maxarea = Math.max(maxarea, (right[j] - left[j]) * height[j]);
}
return maxarea;
}
} ```