题目
标题和出处
标题:最大矩形
出处:85. 最大矩形
难度
8 级
题目描述
要求
给定一个仅包含 0 \texttt{0} 0 和 1 \texttt{1} 1、大小为 rows × cols \texttt{rows} \times \texttt{cols} rows×cols 的二进制矩阵 matrix \texttt{matrix} matrix,找出只包含 1 \texttt{1} 1 的最大矩形,并返回其面积。
示例
示例 1:
输入:
matrix
=
[["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
\texttt{matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]}
matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出:
6
\texttt{6}
6
解释:最大矩形如上图所示。
示例 2:
输入:
matrix
=
[]
\texttt{matrix = []}
matrix = []
输出:
0
\texttt{0}
0
示例 3:
输入:
matrix
=
[["0"]]
\texttt{matrix = [["0"]]}
matrix = [["0"]]
输出:
0
\texttt{0}
0
示例 4:
输入:
matrix
=
[["1"]]
\texttt{matrix = [["1"]]}
matrix = [["1"]]
输出:
1
\texttt{1}
1
示例 5:
输入:
matrix
=
[["0","0"]]
\texttt{matrix = [["0","0"]]}
matrix = [["0","0"]]
输出:
0
\texttt{0}
0
数据范围
- rows = matrix.length \texttt{rows} = \texttt{matrix.length} rows=matrix.length
- cols = matrix[0].length \texttt{cols} = \texttt{matrix[0].length} cols=matrix[0].length
- 0 ≤ row, cols ≤ 200 \texttt{0} \le \texttt{row, cols} \le \texttt{200} 0≤row, cols≤200
- matrix[i][j] \texttt{matrix[i][j]} matrix[i][j] 为 ‘0’ \texttt{`0'} ‘0’ 或 ‘1’ \texttt{`1'} ‘1’
解法
思路和算法
只要记录矩阵中的每个元素 1 1 1 及其上边的连续 1 1 1 的数量,即可使用「柱状图中最大的矩形」的方法求解。具体而言,创建一个和 matrix \textit{matrix} matrix 相同大小的矩阵,新矩阵中的每个元素为 matrix \textit{matrix} matrix 中相同位置的元素及其上边的连续 1 1 1 的数量,特别地,对于 matrix \textit{matrix} matrix 中的元素 0 0 0,新矩阵中的对应元素是 0 0 0。
示例 1 的 matrix \textit{matrix} matrix 如下:
1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 \begin{matrix} 1 & 0 & 1 & 0 & 0 \\ 1 & 0 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 0 & 0 & 1 & 0 \end{matrix} 11110010111001110110
对应的新矩阵如下:
1 0 1 0 0 2 0 2 1 1 3 1 3 2 2 4 0 0 3 0 \begin{matrix} 1 & 0 & 1 & 0 & 0 \\ 2 & 0 & 2 & 1 & 1 \\ 3 & 1 & 3 & 2 & 2 \\ 4 & 0 & 0 & 3 & 0 \end{matrix} 12340010123001230120
对于新矩阵中的每一行,其中的元素可以看成是以这一行为底的柱状图的每个柱子的高度。因此,在计算出新矩阵之后,遍历新矩阵的每一行,使用「柱状图中最大的矩形」的方法计算以这一行为底的最大矩形面积,遍历全部行之后即可得到矩阵中只包含 1 1 1 的最大矩形面积。
实现方面,并不需要事先计算出新矩阵,而是可以在遍历 matrix \textit{matrix} matrix 的过程中计算,每次计算一行。
具体做法是,创建长度为 cols \textit{cols} cols 的数组 heights \textit{heights} heights,初始时 heights \textit{heights} heights 的每个元素都是 0 0 0,依次遍历 matrix \textit{matrix} matrix 的每一行,进行如下操作:
-
对于 matrix \textit{matrix} matrix 的当前行的每个元素,如果该元素是 0 0 0 则将 heights \textit{heights} heights 的对应元素设为 0 0 0,如果该元素是 1 1 1 则将 heights \textit{heights} heights 的对应元素加 1 1 1,此时 heights \textit{heights} heights 的每个元素为 matrix \textit{matrix} matrix 中的对应位置的元素及其上边的连续 1 1 1 的数量;
-
遍历完 matrix \textit{matrix} matrix 的当前行之后,根据 heights \textit{heights} heights 计算以当前行为底的最大矩形面积,并更新结果。
遍历结束之后返回结果。
代码
class Solution {
public int maximalRectangle(char[][] matrix) {
if (matrix.length == 0 || matrix[0].length == 0) {
return 0;
}
int maxArea = 0;
int rows = matrix.length, cols = matrix[0].length;
int[] heights = new int[cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (matrix[i][j] == '0') {
heights[j] = 0;
} else {
heights[j]++;
}
}
maxArea = Math.max(maxArea, getMaxArea(heights));
}
return maxArea;
}
public int getMaxArea(int[] heights) {
int length = heights.length;
int[] left = new int[length];
int[] right = new int[length];
Arrays.fill(left, -1);
Arrays.fill(right, length);
Deque<Integer> stack = new ArrayDeque<Integer>();
for (int i = 0; i < length; i++) {
int height = heights[i];
while (!stack.isEmpty() && heights[stack.peek()] >= height) {
right[stack.pop()] = i;
}
if (!stack.isEmpty()) {
left[i] = stack.peek();
}
stack.push(i);
}
int area = 0;
for (int i = 0; i < length; i++) {
area = Math.max(area, (right[i] - left[i] - 1) * heights[i]);
}
return area;
}
}
复杂度分析
-
时间复杂度: O ( rows × cols ) O(\textit{rows} \times \textit{cols}) O(rows×cols),其中 rows \textit{rows} rows 和 cols \textit{cols} cols 分别是矩阵 matrix \textit{matrix} matrix 的行数和列数。需要遍历矩阵 matrix \textit{matrix} matrix 的每一行,行数是 rows \textit{rows} rows,对于每一行,计算 heights \textit{heights} heights 和计算以这一行为底的最大矩形面积的时间复杂度都是 O ( cols ) O(\textit{cols}) O(cols),因此总时间复杂度是 O ( rows × cols ) O(\textit{rows} \times \textit{cols}) O(rows×cols)。
-
空间复杂度: O ( cols ) O(\textit{cols}) O(cols),其中 cols \textit{cols} cols 是矩阵 matrix \textit{matrix} matrix 的列数。数组 heights \textit{heights} heights 的长度是 cols \textit{cols} cols,计算以每一行为底的最大矩形面积的空间复杂度是 O ( cols ) O(\textit{cols}) O(cols),因此总空间复杂度是 O ( cols ) O(\textit{cols}) O(cols)。