给定一个仅包含 0
和 1
、大小为 rows x cols
的二维二进制矩阵,找出只包含 1
的最大矩形,并返回其面积。
输入:matrix = [["1","0","1","0","0"],
["1","0","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"]]
输出:6
解释:最大矩形如上图所示。
思路与代码
暴力解法
通过遍历所有的(x1, y1) (x2, y2) 坐标,并以它们为对角顶点来完成。
时间复杂度:O(N³M³)
其中遍历全部(x1, y1) (x2, y2)
坐标的时间复杂度为O(N²M²)
,遍历以该两点为对角线的矩形的复杂度为O(NM)
。故总体复杂度为O(NM) * O(N²M²) = O(N³M³)
空间复杂度 O(1)
动态规划优化
dp[i][j]用来表示以第(i,j)坐标为右边界的连续矩形宽度大小。只是表示改行连续矩形宽度大小。
这样通过遍历所有(i,j),我们可以求出以(i,j)结尾的最大矩形大小。通过比较dp[0][j]
到dp[i][j]
的最大宽度,来确定以(i,j)结尾的最大矩形大小。
时间复杂度:O(N²M)
空间复杂度:O(NM)
class Solution {
public int maximalRectangle(char[][] matrix) {
int row = matrix.length;
if (row == 0) return 0;
int col = matrix[0].length;
int[][] dp = new int[row][col];
int max = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (matrix[i][j] == '0') continue;
if (j == 0)
dp[i][j] = matrix[i][j] == '1' ? 1 : 0;
else
dp[i][j] = matrix[i][j] == '1' ? 1 + dp[i][j-1] : 0;
int width = dp[i][j];
for (int index = i; index >= 0; index--){
width= Math.min(dp[index][j], width);
max = Math.max(max, width* (i - index + 1));
}
}
}
return max;
}
}
栈解法
其实对每一行求出柱子高度heights[],传入LeetCode 84 柱状图中最大的矩形(困难)的解法就可以了。
时间复杂度:O(NM)
空间复杂度:O(NM)
class Solution {
public int maximalRectangle(char[][] matrix) {
int row = matrix.length;
if (row == 0) return 0;
int col = matrix[0].length;
int max = 0;
int[] heights = new int[col];
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (matrix[i][j] == '1') {
heights[j] += 1;
} else {
heights[j] = 0;
}
}
max = Math.max(max, largestRectangleArea(heights));
}
return max;
}
public int largestRectangleArea(int[] heights) {
Deque<Integer[]> stack = new ArrayDeque();
int max = 0;
stack.push(new Integer[]{-1, -1});
for (int i = 0; i < heights.length; i++) {
if (heights[i] > stack.peek()[0]){
}else if (heights[i] < stack.peek()[0]){
while (heights[i] < stack.peek()[0]) {
Integer[] lastRect = stack.pop();
max = Math.max(max, lastRect[0] * (i - 1 - stack.peek()[1]));
}
}else{
stack.pop();
}
stack.push(new Integer[]{heights[i], i});
}
while (stack.size() > 1) {
Integer[] rect = stack.pop();
max = Math.max(max, rect[0] * (heights.length - 1 - stack.peek()[1]));
}
return max;
}
}