给定一个仅包含 0
和 1
、大小为 rows x cols
的二维二进制矩阵,找出只包含 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[0].length
1 <= row, cols <= 200
matrix[i][j]
为'0'
或'1'
方法一:单调栈
把每一行视为柱状图的底部,对每一行求柱状图的最大面积即可。
时间复杂度
class Solution:
def maximalRectangle(self, matrix: List[List[str]]) -> int:
heights = [0] * len(matrix[0])
ans = 0
for row in matrix:
for j, v in enumerate(row):
if v == "1":
heights[j] += 1
else:
heights[j] = 0
ans = max(ans, self.largestRectangleArea(heights))
return ans
def largestRectangleArea(self, heights: List[int]) -> int:
n = len(heights)
stk = []
left = [-1] * n
right = [n] * n
for i, h in enumerate(heights):
while stk and heights[stk[-1]] >= h:
stk.pop()
if stk:
left[i] = stk[-1]
stk.append(i)
stk = []
for i in range(n - 1, -1, -1):
h = heights[i]
while stk and heights[stk[-1]] >= h:
stk.pop()
if stk:
right[i] = stk[-1]
stk.append(i)
return max(h * (right[i] - left[i] - 1) for i, h in enumerate(heights))
class Solution {
public int maximalRectangle(char[][] matrix) {
int n = matrix[0].length;
int[] heights = new int[n];
int ans = 0;
for (var row : matrix) {
for (int j = 0; j < n; ++j) {
if (row[j] == '1') {
heights[j] += 1;
} else {
heights[j] = 0;
}
}
ans = Math.max(ans, largestRectangleArea(heights));
}
return ans;
}
private int largestRectangleArea(int[] heights) {
int res = 0, n = heights.length;
Deque<Integer> stk = new ArrayDeque<>();
int[] left = new int[n];
int[] right = new int[n];
Arrays.fill(right, n);
for (int i = 0; i < n; ++i) {
while (!stk.isEmpty() && heights[stk.peek()] >= heights[i]) {
right[stk.pop()] = i;
}
left[i] = stk.isEmpty() ? -1 : stk.peek();
stk.push(i);
}
for (int i = 0; i < n; ++i) {
res = Math.max(res, heights[i] * (right[i] - left[i] - 1));
}
return res;
}
}
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
int n = matrix[0].size();
vector<int> heights(n);
int ans = 0;
for (auto& row : matrix) {
for (int j = 0; j < n; ++j) {
if (row[j] == '1')
++heights[j];
else
heights[j] = 0;
}
ans = max(ans, largestRectangleArea(heights));
}
return ans;
}
int largestRectangleArea(vector<int>& heights) {
int res = 0, n = heights.size();
stack<int> stk;
vector<int> left(n, -1);
vector<int> right(n, n);
for (int i = 0; i < n; ++i) {
while (!stk.empty() && heights[stk.top()] >= heights[i]) {
right[stk.top()] = i;
stk.pop();
}
if (!stk.empty()) left[i] = stk.top();
stk.push(i);
}
for (int i = 0; i < n; ++i)
res = max(res, heights[i] * (right[i] - left[i] - 1));
return res;
}
};
func maximalRectangle(matrix [][]byte) int {
n := len(matrix[0])
heights := make([]int, n)
ans := 0
for _, row := range matrix {
for j, v := range row {
if v == '1' {
heights[j]++
} else {
heights[j] = 0
}
}
ans = max(ans, largestRectangleArea(heights))
}
return ans
}
func largestRectangleArea(heights []int) int {
res, n := 0, len(heights)
var stk []int
left, right := make([]int, n), make([]int, n)
for i := range right {
right[i] = n
}
for i, h := range heights {
for len(stk) > 0 && heights[stk[len(stk)-1]] >= h {
right[stk[len(stk)-1]] = i
stk = stk[:len(stk)-1]
}
if len(stk) > 0 {
left[i] = stk[len(stk)-1]
} else {
left[i] = -1
}
stk = append(stk, i)
}
for i, h := range heights {
res = max(res, h*(right[i]-left[i]-1))
}
return res
}
func max(a, b int) int {
if a > b {
return a
}
return b
}