最大矩形面积问题 | 豆包MarsCode AI刷题

43 阅读2分钟

问题描述

小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) 的最大值。

问题理解

我们需要在一个数组中找到任意 k 个相邻元素所能形成的最大矩形面积。矩形的面积定义为这 k 个元素中的最小值乘以 k

数据结构选择

为了高效地解决这个问题,我们可以考虑使用栈来辅助计算。当我们遍历数组时,栈中的元素总是保持递增的顺序。这样,当我们遇到一个比栈顶元素小的高度时,我们可以确定栈顶元素对应的高度不能再向右扩展,因此可以计算以该高度为最小高度的矩形面积。

算法步骤

  1. 初始化:创建一个栈来存储数组的索引,初始化 maxArea 为 0。

  2. 遍历数组

    • 如果当前高度小于栈顶元素对应的高度,则弹出栈顶元素,并计算以该高度为最小高度的矩形面积。
    • 计算面积时,宽度为当前索引与新栈顶元素索引的差值。
    • 更新 maxArea
  3. 处理栈中剩余元素:遍历结束后,栈中可能还剩下一些元素,这些元素对应的高度可以延伸到数组的末尾,计算这些矩形的面积并更新 maxArea

关键点

  • 栈的使用:栈中存储的是数组的索引,而不是高度本身。
  • 面积计算:每次弹出栈顶元素时,计算以该高度为最小高度的矩形面积。

具体代码

import java.util.Stack;

public class Main {
    public static int solution(int n, int[] array) {
        // 使用栈来辅助计算
        Stack<Integer> stack = new Stack<>();
        int maxArea = 0;
        
        // 遍历数组
        for (int i = 0; i < n; i++) {
            // 当栈不为空且当前高度小于栈顶高度时
            while (!stack.isEmpty() && array[i] < array[stack.peek()]) {
                // 弹出栈顶元素并计算面积
                int height = array[stack.pop()];
                int width = stack.isEmpty() ? i : i - stack.peek() - 1;
                maxArea = Math.max(maxArea, height * width);
            }
            // 将当前索引入栈
            stack.push(i);
        }
        
        // 处理栈中剩余的元素
        while (!stack.isEmpty()) {
            int height = array[stack.pop()];
            int width = stack.isEmpty() ? n : n - stack.peek() - 1;
            maxArea = Math.max(maxArea, height * 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);
        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);
    }
}