解题思路与代码实现
问题描述
小S最近在分析一个数组 ℎ1,ℎ2,…,ℎ𝑁,数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 𝑘k 个相邻元素时,如何计算它们所能形成的最大矩形面积。对于 𝑘k 个相邻的元素,我们定义其矩形的最大面积为:
𝑅(𝑘)=𝑘×min(ℎ[𝑖],ℎ[𝑖+1],…,ℎ[𝑖+𝑘−1])
即,𝑅(𝑘) 的值为这 𝑘 个相邻元素中的最小值乘以 𝑘。现在,小S希望你能帮他找出对于任意 𝑘,𝑅(𝑘) 的最大值。
测试样例
- 样例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
- 输入:
解题思路
这个问题与直方图中最大的矩形面积问题非常相似。我们可以利用类似的方法,通过单调栈来高效地解决。
步骤解析
-
使用单调栈:
- 我们维护一个单调递增的栈,栈中存储的是柱子的索引。
- 当当前柱子的高度小于栈顶柱子的高度时,意味着栈顶柱子找到了右边第一个比它低的柱子。
- 弹出栈顶柱子,计算以该柱子为最小高度的最大面积。
-
计算面积:
- 对于弹出的柱子 ( h[top] ),其宽度为当前索引 ( i ) 与栈顶新的柱子索引之间的差值减一。
- 计算面积 ( h[top] \times width ),并更新最大面积。
-
遍历结束后的处理:
- 遍历完所有柱子后,可能还有柱子留在栈中,这些柱子的右边没有比它们更低的柱子。
- 依次弹出这些柱子,并计算相应的面积。
-
最终结果:
- 最大的面积即为所求的最大 ( R(k) )。
算法复杂度
- 时间复杂度: ( O(N) ),每个柱子最多被压入和弹出栈一次。
- 空间复杂度: ( O(N) ),用于栈的空间。
代码实现
import java.util.ArrayDeque;
import java.util.Deque;
public class Main {
public static int solution(int n, int[] array) {
// Edit your code here
// 使用栈来存储索引
Deque<Integer> stack = new ArrayDeque<>();
int maxArea = 0;
int i = 0;
while (i < n) {
// 如果当前柱子高度大于栈顶柱子的高度,或者栈为空,则将当前柱子索引压入栈
if (stack.isEmpty() || array[i] >= array[stack.peek()]) {
stack.push(i++);
} else {
// 弹出栈顶柱子,计算面积
int top = stack.pop();
// 计算宽度,注意这里使用 '=' 号进行赋值
int width = stack.isEmpty() ? i : i - stack.peek() - 1;
// 计算面积并更新最大面积
maxArea = Math.max(maxArea, array[top] * width);
}
}
// 处理栈中剩余的柱子
while (!stack.isEmpty()) {
int top = stack.pop();
int width = stack.isEmpty() ? i : i - stack.peek() - 1;
maxArea = Math.max(maxArea, array[top] * width);
}
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);
}
}
代码说明
-
栈的作用:
- 栈中存储的是柱子的索引,且栈内的柱子高度保持递增。
- 通过这个性质,我们可以快速找到每个柱子的左边和右边第一个比它低的柱子。
-
遍历过程:
- 当当前柱子的高度大于或等于栈顶柱子的高度时,将其索引压入栈。
- 否则,弹出栈顶柱子,并计算以弹出柱子为最小高度的矩形面积。
- 继续这个过程,直到当前柱子的高度不再小于栈顶柱子的高度。
-
计算面积:
- 对于弹出的柱子 ( h[top] ),其左边界是当前栈顶柱子(如果有的话),右边界是当前柱子。
- 宽度 ( width = i - stack.peek() - 1 )。
-
处理剩余柱子:
- 遍历完成后,栈中可能还有柱子没有处理完,需要依次弹出并计算面积。
-
测试样例验证:
- 样例1:
- 输入:
n = 5,array = [1, 2, 3, 4, 5] - 最大面积为
9,对应子数组[3, 4, 5],最小值为3,面积为3 * 3 = 9。
- 输入:
- 样例2:
- 输入:
n = 6,array = [5, 4, 3, 2, 1, 6] - 最大面积为
9,对应子数组[5, 4, 3],最小值为3,面积为3 * 3 = 9。
- 输入:
- 样例3:
- 输入:
n = 4,array = [4, 4, 4, 4] - 最大面积为
16,对应整个数组,最小值为4,面积为4 * 4 = 16。
- 输入:
- 样例1:
总结
通过使用单调栈的方法,我们能够高效地找到每个柱子前面和后面第一个比它低的柱子,从而计算出所能形成的最大矩形面积。该算法的时间复杂度为 O(N),适用于大规模的数据处理。