题目链接:https://leetcode.cn/problems/maximal-rectangle/
思路
将矩阵拆分成若干个柱状图,然后直接复用84.柱状图中最大的矩形的解法。
假设有以下矩阵:
矩阵前1行形成的柱状图:1 0 1 0 0
矩阵前2行形成的柱状图:2 0 2 1 1
矩阵前3行形成的柱状图:3 1 3 2 2
矩阵前4行形成的柱状图:4 0 0 3 0
对每个柱状图调用maxArea
求最大矩形面积,取所有面积的最大值即为所求。
Java
class Solution {
public int maximalRectangle(char[][] matrix) {
if (matrix.length == 0) {
return 0;
}
int[] nums = new int[matrix[0].length];
int result = 0;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
nums[j] = matrix[i][j] == '1' ? nums[j] + 1 : 0;
}
result = Math.max(result, maxArea(nums));
}
return result;
}
// 参见 https://leetcode.cn/problems/largest-rectangle-in-histogram/
private int maxArea(int[] nums) {
// left[i]表示nums[i]左边第一个小于nums[i]的元素下标
int[] left = new int[nums.length];
left[0] = -1;
for (int i = 1; i < nums.length; i++) {
int j = i - 1;
while (j != -1 && nums[j] >= nums[i]) {
j = left[j];
}
left[i] = j;
}
// right[i]表示nums[i]右边第一个小于nums[i]的元素下标
int[] right = new int[nums.length];
right[nums.length - 1] = nums.length;
for (int i = nums.length - 2; i >= 0; i--) {
int j = i + 1;
while (j != nums.length && nums[j] >= nums[i]) {
j = right[j];
}
right[i] = j;
}
int result = 0;
for (int i = 0; i < nums.length; i++) {
result = Math.max(result, nums[i] * (right[i] - left[i] - 1));
}
return result;
}
}
Go
func maximalRectangle(nums [][]byte) int {
if len(nums) == 0 {
return 0
}
max := func(a, b int) int {
if a > b {
return a
}
return b
}
// 参见 https://leetcode.cn/problems/largest-rectangle-in-histogram/
maxAreaOfRow := func(nums []int) int {
// left[i]表示nums[i]左边第一个比nums[i]小的元素下标
left := make([]int, len(nums))
left[0] = -1
for i := 1; i < len(nums); i++ {
idx := i - 1
for idx != -1 && nums[idx] >= nums[i] {
idx = left[idx]
}
left[i] = idx
}
// right[i]表示nums[i]右边第一个比nums[i]小的元素下标
right := make([]int, len(nums))
right[len(nums)-1] = len(nums)
for i := len(nums) - 2; i >= 0; i-- {
idx := i + 1
for idx != len(nums) && nums[idx] >= nums[i] {
idx = right[idx]
}
right[i] = idx
}
maxArea := 0
for i := 0; i < len(nums); i++ {
maxArea = max(maxArea, nums[i]*(right[i]-left[i]-1))
}
return maxArea
}
row := make([]int, len(nums[0]))
maxArea := 0
for i := 0; i < len(nums); i++ {
for j := 0; j < len(nums[i]); j++ {
if nums[i][j] == '0' {
row[j] = 0
} else {
row[j]++
}
}
maxArea = max(maxArea, maxAreaOfRow(row))
}
return maxArea
}