给定一个仅包含 0
和 1
的二维二进制矩阵,找出只包含 1
的最大矩形,并返回其面积。
困难
最大矩形
示例 1:
输入: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
示例 4:
输入:matrix = [["1"]]
输出:1
示例 5:
输入:matrix = [["0","0"]]
输出:0
rows == matrix.length
cols == matrix[i].length
0 <= row, cols <= 200
matrix[i][j]
为 '0'
或 '1'
这道题是 LeetCode 第 84 题"柱状图中最大的矩形"的扩展。我们可以将二维矩阵的每一行看作是柱状图的一层,然后利用第 84 题的解法来解决这个问题。
步骤 | 操作 | 说明 |
---|---|---|
1 | 初始化最大面积和高度数组 | 最大面积初始为0,高度数组初始全为0 |
2 | 遍历矩阵的每一行 | 对于每一行,执行步骤3-5 |
3 | 更新高度数组 | 如果当前位置为1,则高度加1;否则高度重置为0 |
4 | 计算当前行对应柱状图的最大矩形面积 | 使用单调栈算法计算 |
5 | 更新最大面积 | 更新最大面积为当前最大面积和新计算的面积中的较大值 |
6 | 返回最大面积 | 返回计算得到的最大面积 |
以示例 1 为例,matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
:
第一行:["1","0","1","0","0"]
[1,0,1,0,0]
第二行:["1","0","1","1","1"]
[2,0,2,1,1]
第三行:["1","1","1","1","1"]
[3,1,3,2,2]
第四行:["1","0","0","1","0"]
[4,0,0,3,0]
最终的最大矩形面积为6。
public class Solution {
public int MaximalRectangle(char[][] matrix) {
if (matrix == null || matrix.Length == 0 || matrix[0].Length == 0) {
return 0;
}
int rows = matrix.Length;
int cols = matrix[0].Length;
int[] heights = new int[cols];
int maxArea = 0;
for (int i = 0; i < rows; i++) {
// 更新高度数组
for (int j = 0; j < cols; j++) {
if (matrix[i][j] == '1') {
heights[j]++;
} else {
heights[j] = 0;
}
}
// 计算当前行对应柱状图的最大矩形面积
maxArea = Math.Max(maxArea, LargestRectangleArea(heights));
}
return maxArea;
}
// 使用单调栈计算柱状图中的最大矩形面积(LeetCode 第 84 题的解法)
private int LargestRectangleArea(int[] heights) {
int n = heights.Length;
if (n == 0) return 0;
if (n == 1) return heights[0];
// 在数组两端添加高度为0的柱子
int[] newHeights = new int[n + 2];
Array.Copy(heights, 0, newHeights, 1, n);
n += 2;
heights = newHeights;
Stack<int> stack = new Stack<int>();
int maxArea = 0;
for (int i = 0; i < n; i++) {
while (stack.Count > 0 && heights[i] < heights[stack.Peek()]) {
int height = heights[stack.Pop()];
int width = i - stack.Peek() - 1;
maxArea = Math.Max(maxArea, height * width);
}
stack.Push(i);
}
return maxArea;
}
}
class Solution:
def maximalRectangle(self, matrix: List[List[str]]) -> int:
if not matrix or not matrix[0]:
return 0
rows, cols = len(matrix), len(matrix[0])
heights = [0] * cols
max_area = 0
for i in range(rows):
# 更新高度数组
for j in range(cols):
if matrix[i][j] == '1':
heights[j] += 1
else:
heights[j] = 0
# 计算当前行对应柱状图的最大矩形面积
max_area = max(max_area, self.largestRectangleArea(heights))
return max_area
# 使用单调栈计算柱状图中的最大矩形面积(LeetCode 第 84 题的解法)
def largestRectangleArea(self, heights: List[int]) -> int:
n = len(heights)
if n == 0:
return 0
if n == 1:
return heights[0]
# 在数组两端添加高度为0的柱子
heights = [0] + heights + [0]
n += 2
stack = [0] # 栈初始化,放入第一个柱子的索引
max_area = 0
for i in range(1, n):
while stack and heights[i] < heights[stack[-1]]:
height = heights[stack.pop()]
width = i - stack[-1] - 1
max_area = max(max_area, height * width)
stack.append(i)
return max_area
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
if (matrix.empty() || matrix[0].empty()) {
return 0;
}
int rows = matrix.size();
int cols = matrix[0].size();
vector<int> heights(cols, 0);
int maxArea = 0;
for (int i = 0; i < rows; ++i) {
// 更新高度数组
for (int j = 0; j < cols; ++j) {
if (matrix[i][j] == '1') {
heights[j]++;
} else {
heights[j] = 0;
}
}
// 计算当前行对应柱状图的最大矩形面积
maxArea = max(maxArea, largestRectangleArea(heights));
}
return maxArea;
}
// 使用单调栈计算柱状图中的最大矩形面积(LeetCode 第 84 题的解法)
int largestRectangleArea(vector<int>& heights) {
int n = heights.size();
if (n == 0) return 0;
if (n == 1) return heights[0];
// 在数组两端添加高度为0的柱子
heights.insert(heights.begin(), 0);
heights.push_back(0);
n += 2;
stack<int> stk;
stk.push(0); // 栈初始化,放入第一个柱子的索引
int maxArea = 0;
for (int i = 1; i < n; ++i) {
while (!stk.empty() && heights[i] < heights[stk.top()]) {
int height = heights[stk.top()];
stk.pop();
int width = i - stk.top() - 1;
maxArea = max(maxArea, height * width);
}
stk.push(i);
}
return maxArea;
}
};
解法 | 时间复杂度 | 空间复杂度 | 优点 | 缺点 |
---|---|---|---|---|
暴力解法 | O(rows²×cols²) | O(1) | 思路简单,容易理解 | 时间复杂度高,会超时 |
基于柱状图的动态规划 | O(rows×cols) | O(cols) | 时间复杂度低,利用已有解法 | 需要理解单调栈和动态规划的概念 |
动态规划(优化) | O(rows×cols) | O(cols) | 不需要使用单调栈,直接计算 | 实现复杂,需要维护多个数组 |