柱状图中的最大矩形
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。
图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。
示例:
输入: [2,1,5,6,2,3]
输出: 10
单调栈
class Solution {
public int largestRectangleArea(int[] heights) {
int n = heights.length;
int[] left = new int[n];
int[] right = new int[n];
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < n; ++i) {
while (!stack.isEmpty() && heights[stack.peek()] >= heights[i])
stack.pop();
left[i] = stack.isEmpty() ? -1 : stack.peek();
stack.push(i);
}
stack.clear();
for (int i = n - 1; i >= 0; --i) {
while (!stack.isEmpty() && heights[stack.peek()] >= heights[i])
stack.pop();
right[i] = stack.isEmpty() ? n : stack.peek();
stack.push(i);
}
int max = 0;
for (int i = 0; i < n; i++)
max = Math.max(max, (right[i] - left[i] - 1) * heights[i]);
return max;
}
}
单调栈 + 常数优化
class Solution {
public int largestRectangleArea(int[] heights) {
int n = heights.length;
int[] left = new int[n];
int[] right = new int[n];
Arrays.fill(right, n);
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < n; ++i) {
while (!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
right[stack.peek()] = i;
stack.pop();
}
left[i] = stack.isEmpty() ? -1 : stack.peek();
stack.push(i);
}
int max = 0;
for (int i = 0; i < n; i++)
max = Math.max(max, (right[i] - left[i] - 1) * heights[i]);
return max;
}
}
左右两边增加元素
class Solution {
public int largestRectangleArea(int[] heights) {
int n = heights.length;
int[] newHeights = new int[n + 2];
newHeights[0] = 0;
newHeights[n + 1] = 0;
System.arraycopy(heights, 0, newHeights, 1, n);
n += 2;
int max = 0;
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
for (int i = 1; i < n; i++) {
while (newHeights[i] < newHeights[stack.peek()]) {
max = Math.max(max, newHeights[stack.pop()] * (i - stack.peek() - 1));
}
stack.push(i);
}
return max;
}
}
最大矩形
给定一个仅包含 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
暴力法
class Solution {
public int maximalRectangle(char[][] matrix) {
int rows = matrix.length;
if (rows == 0)
return 0;
int cols = matrix[0].length;
int[][] left = new int[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (matrix[i][j] == '1')
left[i][j] = (j == 0 ? 0 : left[i][j - 1]) + 1;
}
}
int max = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (matrix[i][j] == '1') {
int width = left[i][j];
int area = width;
for (int k = i - 1; k >= 0; k--) {
if (left[k][j] == 0)
break;
width = Math.min(width, left[k][j]);
area = Math.max(area, (i - k + 1) * width);
}
max = Math.max(area, max);
}
}
}
return max;
}
}
单调栈
与柱状图中的最大矩形相似
class Solution {
public int maximalRectangle(char[][] matrix) {
int rows = matrix.length;
if (rows == 0)
return 0;
int cols = matrix[0].length;
int[] heights = new int[cols + 1];
int maxArea = 0;
for (int i = 0; i < rows; i++) {
Stack<Integer> stack = new Stack<>();
heights[cols] = 0;
for (int j = 0; j <= cols; j++) {
if (j < cols) {
if (matrix[i][j] == '1')
heights[j] += 1;
else
heights[j] = 0;
}
if (stack.isEmpty() || heights[j] >= heights[stack.peek()]) {
stack.push(j);
} else {
while (!stack.isEmpty() && heights[j] < heights[stack.peek()]) {
int height = heights[stack.pop()];
int left = stack.isEmpty() ? -1 : stack.peek();
int area = (j - left - 1) * height;
maxArea = Math.max(area, maxArea);
}
stack.push(j);
}
}
}
return maxArea;
}
}
矩形面积
在二维平面上计算出两个由直线构成的矩形重叠后形成的总面积。
每个矩形由其左下顶点和右上顶点坐标表示,如图所示。
示例:
输入: -3, 0, 3, 4, 0, -1, 9, 2
输出: 45
排序
class Solution {
public int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) {
int size1 = (C - A) * (D - B);
int size2 = (G - E) * (H - F);
if (C <= E || G <= A || H <= B || D <= F)
return size1 + size2;
int[] x = new int[]{A, C, E, G};
int[] y = new int[]{B, D, F, H};
Arrays.sort(x);
Arrays.sort(y);
int size3 = (x[2] - x[1]) * (y[2] - y[1]);
return size1 + size2 - size3;
}
}
比较判断
class Solution {
public int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) {
int size1 = (C - A) * (D - B);
int size2 = (G - E) * (H - F);
if (C <= E || G <= A || H <= B || D <= F)
return size1 + size2;
int x1 = Math.max(A, E);
int x2 = Math.min(C, G);
int y1 = Math.max(B, F);
int y2 = Math.min(D, H);
int size3 = (x2 - x1) * (y2 - y1);
return size1 + size2 - size3;
}
}
下一个更大元素
给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。
请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。
示例 1:
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
对于 num1 中的数字 4 ,你无法在第二个数组中找到下一个更大的数字,因此输出 -1 。
对于 num1 中的数字 1 ,第二个数组中数字1右边的下一个较大数字是 3 。
对于 num1 中的数字 2 ,第二个数组中没有下一个更大的数字,因此输出 -1 。
示例 2:
输入: nums1 = [2,4], nums2 = [1,2,3,4].
输出: [3,-1]
解释:
对于 num1 中的数字 2 ,第二个数组中的下一个较大数字是 3 。
对于 num1 中的数字 4 ,第二个数组中没有下一个更大的数字,因此输出 -1 。
单调栈
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
int[] map = new int[10001];
int len1 = nums1.length, len2 = nums2.length;
map[nums2[len2 - 1]] = -1;
Deque<Integer> stack = new LinkedList<>();
for (int i = 0; i < len2; i++) {
while (!stack.isEmpty() && stack.peek() < nums2[i])
map[stack.pop()] = nums2[i];
stack.push(nums2[i]);
}
int[] result = new int[len1];
for (int i = 0; i < len1; i++)
result[i] = map[nums1[i]] == 0 ? -1 : map[nums1[i]];
return result;
}
}