最大矩形面积问题
题目如下:
问题描述
小S最近在分析一个数组 h1,h2,...,hNh1,h2,...,hN,数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 kk 个相邻元素时,如何计算它们所能形成的最大矩形面积。
对于 kk 个相邻的元素,我们定义其矩形的最大面积为:
R(k)=k×min(h[i],h[i+1],...,h[i+k−1])R(k)=k×min(h[i],h[i+1],...,h[i+k−1])
即,R(k)R(k) 的值为这 kk 个相邻元素中的最小值乘以 kk。现在,小S希望你能帮他找出对于任意 kk,R(k)R(k) 的最大值。
测试样例
样例1:
输入:
n = 5, array = [1, 2, 3, 4, 5]
输出:9
样例2:
输入:
n = 6, array = [5, 4, 3, 2, 1, 6]
输出:9
样例3:
输入:
n = 4, array = [4, 4, 4, 4]
输出:16
思路解析
这个问题可以转化为经典的“柱状图中最大的矩形”问题。我们需要找到一个方法来计算给定数组中所有可能的 kk 个连续元素形成的矩形的最大面积。一种有效的方法是使用单调栈(Monotonic Stack)来解决这个问题。
-
单调栈的应用:
- 单调栈是一种特殊的栈结构,其中栈内的元素保持递增或递减的顺序。
- 在本问题中,我们可以使用一个单调递增栈来存储每个柱子的高度索引。
- 当遇到一个比栈顶元素小的高度时,说明当前栈顶元素不能再扩展了,此时可以计算以栈顶元素为高度的最大矩形面积。
-
算法步骤:
-
初始化一个空栈和一个变量
maxArea用于记录最大矩形面积。 -
遍历整个数组,对于每个元素:
- 如果栈为空或当前元素大于等于栈顶元素,则将当前元素的索引入栈。
- 否则,弹出栈顶元素,并计算以该元素为高度的最大矩形面积。
-
最后处理栈中剩余的元素,计算相应的矩形面积。
-
-
时间复杂度:
- 由于每个元素最多只会被入栈和出栈一次,因此时间复杂度为 O(n)O(n)。
代码解析
-
初始化:
java 深色版本 Stack<Integer> stack = new Stack<>(); int maxArea = 0; int i = 0;- 初始化一个空栈
stack和变量maxArea用于记录最大矩形面积。 - 变量
i用于遍历数组。
- 初始化一个空栈
-
主循环:
java 深色版本 while (i < n) { if (stack.isEmpty() || height[i] >= height[stack.peek()]) { stack.push(i++); } else { int top = stack.pop(); int width = stack.isEmpty() ? i : i - stack.peek() - 1; int area = height[top] * width; maxArea = Math.max(maxArea, area); } }- 如果栈为空或当前元素大于等于栈顶元素,则将当前元素的索引入栈。
- 否则,弹出栈顶元素,计算以该元素为高度的最大矩形面积。宽度由当前索引和下一个栈顶元素的索引决定。
-
处理剩余元素:
java 深色版本 while (!stack.isEmpty()) { int top = stack.pop(); int width = stack.isEmpty() ? i : i - stack.peek() - 1; int area = height[top] * width; maxArea = Math.max(maxArea, area); }- 处理栈中剩余的元素,计算相应的矩形面积。
代码解答
import java.util.Stack;
public class Main {
public static int solution(int n, int[] height) {
// Edit your code here
Stack<Integer> stack = new Stack<>();
int maxArea = 0;
int i = 0;
while (i < n) {
// 如果栈为空或者当前高度大于栈顶高度,则将当前高度的索引入栈
if (stack.isEmpty() || height[i] >= height[stack.peek()]) {
stack.push(i++);
} else {
// 否则,弹出栈顶元素,计算以栈顶元素为高度的最大矩形面积
int top = stack.pop();
int area = height[top] * (stack.isEmpty() ? i : i - stack.peek() - 1);
maxArea = Math.max(maxArea, area);
}
}
// 处理栈中剩余的元素
while (!stack.isEmpty()) {
int top = stack.pop();
int area = height[top] * (stack.isEmpty() ? i : i - stack.peek() - 1);
maxArea = Math.max(maxArea, area);
}
return maxArea;
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution(5, new int[]{1, 2, 3, 4, 5}) == 9);
System.out.println(solution(6, new int[]{5, 4, 3, 2, 1, 6}) == 9);
System.out.println(solution(4, new int[]{4, 4, 4, 4}) == 16);
}
}