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

86 阅读4分钟

问题描述

小S最近在分析一个数组 h1,h2,...,hN,数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 k 个相邻元素时,如何计算它们所能形成的最大矩形面积。

对于 k 个相邻的元素,我们定义其矩形的最大面积为:

R(k)=k×min(h[i],h[i+1],...,h[i+k−1])

即,R(k) 的值为这 k 个相邻元素中的最小值乘以 k。现在,小S希望你能帮他找出对于任意 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

解题思路

解法一:暴力法(枚举法)

  • 遍历所有可能的子数组长度 k (从 1 到 n)。

  • 对于每个 k,从数组起点开始遍历每个子数组,计算其最小值 min(h[i:i+k]) 并乘以 k。

  • 记录每个子数组长度 k 的最大矩形面积,最后返回所有值中的最大值。

Java代码实现

public static int solution(int n, int[] array) {
        int maxArea = 0;

        // 枚举所有可能的子数组长度 k
        for (int k = 1; k <= n; k++) {
            for (int i = 0; i <= n - k; i++) {
                // 找到长度为 k 的子数组中的最小值
                int minHeight = Integer.MAX_VALUE;
                for (int j = i; j < i + k; j++) {
                    minHeight = Math.min(minHeight, array[j]);
                }
                // 更新最大面积
                maxArea = Math.max(maxArea, minHeight * k);
            }
        }

        return maxArea;
    }

时间复杂度

  • 时间复杂度:O(n2n^2) (枚举所有子数组,计算最小值需要O(k))。

  • 空间复杂度:O(1)。

解法二:单调栈法

此问题可以转化为直方图最大矩形问题,核心思路是:

  1. 利用单调栈快速找到每个柱形的左右边界。
  2. 每个柱形高度 h[i] 作为最小值时,可以形成的最大矩形宽度为: 宽度=右边界−左边界−1
  3. 矩形面积为: h[i]×宽度h[i]
  4. 遍历所有柱形,返回最大矩形面积。

Java代码实现

 public static int solution(int n, int[] array) {
        // Edit your code here
        int res = 0, max = 0, len = n;
        Stack<Integer> st = new Stack<>();

        int[] newArray = new int[len + 2];
        newArray[0] = 0;
        newArray[newArray.length - 1] = 0;
        for (int i = 0; i < array.length; i++) {
            newArray[i + 1] = array[i];
        }

        st.push(0);
        for (int right = 0; right < newArray.length; right++) {
            while (!st.isEmpty()) {
                int mid = st.peek();
                if (newArray[right] < newArray[mid]) {
                    st.pop();
                    int left = st.peek();
                    int h = newArray[mid];
                    int w = right - left - 1;

                    max = Math.max(max, w * h);
                } else {
                    break;
                }
            }

            st.push(right);
        }

        return max;
    }

时间复杂度

  • 时间复杂度:O(n)(每个柱形入栈出栈一次)。

  • 空间复杂度:O(n)(存储左右边界和栈)。

学习心得

单调栈思想

它是特殊栈结构,栈内元素需保持单调递增或递减性。按顺序遍历数据序列,栈空时新元素直接入栈;栈不空时,若新元素符合栈的单调性要求则入栈,若不符合,就不断弹出栈顶元素并做相应处理,直至栈空或新元素满足单调性要求后再入栈。

单调栈适合解决以下几类问题:

  • 寻找下一个更大(小)元素:比如在整数数组中找各元素右边首个更大(小)元素,或计算柱状图最大矩形面积时确定各柱子对应的相关情况。
  • 区间最值查询:特定条件下可快速确定满足单调性要求的子区间最值。
  • 匹配括号相关:判断括号是否匹配以及确定匹配括号对位置等。
  • 维护有序序列及快速查询:动态维护有序序列,便于快速查询元素位置及相邻元素等信息。

知识点延伸

  1. 单调栈技巧
    单调栈常用于快速计算左右边界问题,例如:

    • 直方图最大矩形面积。
    • 滑动窗口最大值。
    • 股票问题。
  2. 时间复杂度优化思路
    从暴力法到单调栈的优化,核心在于避免重复计算(如多次求最小值)。

  3. 延伸问题

    • 给定一个二维矩阵,求矩形区域的最大面积(最大子矩形问题)。
    • 滑动窗口内最小值或最大值问题。

通过不同解法的实现,我们可以对算法效率和数据结构应用有更深入的理解。