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

82 阅读3分钟

最大矩形面积问题的深入解析:基于栈的优化解法

问题描述

在一组高度数组中,找到任意连续的 k 个元素能够构成的最大矩形面积。

输入:

  • 一个数组表示高度。
  • 输出矩形的最大面积。

解题思路

对于这个问题,我们可以借助单调栈的思想来优化解法。以下是实现过程的详细分析。

解法概要

  1. 利用单调栈维护一个递增高度序列。
  2. 当遇到当前高度小于栈顶高度时,计算以栈顶高度为最小值的矩形面积。
  3. 在数组首尾添加哨兵值(高度为0),确保所有柱体都能计算。

详细步骤

  1. 数组预处理

    • 为避免处理边界问题,在数组前后分别添加高度为 0 的哨兵值。
    • 新数组长度为 n + 2
  2. 遍历高度数组

    • 利用栈存储柱状图的索引。
    • 如果当前高度小于栈顶高度,则开始计算矩形面积。
  3. 计算面积

    • 弹出栈顶索引,设其高度为矩形最小高度。
    • 宽度为当前索引与栈顶索引的差值减 1
    • 更新最大面积。
  4. 最终结果

    • 遍历结束后,最大面积即为结果。

代码实现

import java.util.Stack;

public class Main {

    public static int solution(int n, int[] heights) {
        // 创建一个栈,保存每个高度的索引
        Stack<Integer> stack = new Stack<>();
        int maxArea = 0;

        // 为了处理边界情况,在原数组前后分别添加一个高度为0的哨兵元素
        int[] newHeights = new int[n + 2];
        System.arraycopy(heights, 0, newHeights, 1, n);

        // 遍历所有的柱状图高度
        for (int i = 0; i < newHeights.length; i++) {
            // 如果当前高度比栈顶的高度小,说明可以计算以栈顶高度为最小值的面积
            while (!stack.isEmpty() && newHeights[i] < newHeights[stack.peek()]) {
                int h = newHeights[stack.pop()]; // 栈顶元素作为高度
                int width = i - stack.peek() - 1; // 计算宽度
                maxArea = Math.max(maxArea, h * width); // 更新最大面积
            }
            stack.push(i); // 当前索引入栈
        }

        return maxArea;
    }

    public static void main(String[] args) {
        // 测试用例
        System.out.println(solution(5, new int[]{1, 2, 3, 4, 5}) == 9);
        System.out.println(solution(5, new int[]{5, 4, 3, 2, 1}) == 9);
        System.out.println(solution(6, new int[]{2, 1, 5, 6, 2, 3}) == 10);
    }
}

代码分析

  1. 单调栈的维护

    • 栈中存储的是高度的索引,并且对应的高度保持递增。
    • 遇到更小的高度时,弹出栈顶进行面积计算。
  2. 面积计算的核心公式

    • 高度:弹出栈顶的高度。
    • 宽度:i - stack.peek() - 1,其中 i 是当前索引,stack.peek() 是栈新的栈顶。
    • 面积:height * width
  3. 哨兵的作用

    • 在数组前后加入高度为 0 的哨兵,确保可以计算所有柱体的面积。
  4. 时间复杂度

    • 每个元素最多被压入和弹出一次,时间复杂度为 O(n)

测试用例解析

用例1

  • 输入:[1, 2, 3, 4, 5]

  • 过程:

    • 栈变化:[1] -> [1,2] -> [1,2,3] -> [1,2,3,4] -> [1,2,3,4,5] -> ...
    • 面积计算:5*1=5, 4*2=8, 3*3=9
  • 输出:9

用例2

  • 输入:[5, 4, 3, 2, 1]

  • 过程:

    • 栈变化:逐渐弹出较大的高度。
    • 面积计算:5*1=5, 4*2=8, 3*3=9
  • 输出:9

用例3

  • 输入:[2, 1, 5, 6, 2, 3]

  • 过程:

    • 栈变化:弹出较小高度,逐步计算面积。
    • 面积计算:6*1=6, 5*2=10
  • 输出:10


个人思考与扩展

  1. 单调栈的适用场景

    • 单调栈适合解决连续性子问题,如:

      • 柱状图最大矩形面积。
      • 下一个更大元素的问题。
  2. 代码优化

    • 当前实现清晰,但可以通过内存池优化栈存储以节省空间。
  3. 与其他算法的对比

    • 动态规划:处理类似问题时会保存更多中间状态,适合多次查询场景。
    • 暴力法:复杂度 O(n^2),仅适合小规模数据。

单调栈是一个强大的工具,在解决矩形面积和类似问题时,不仅效率高,还能确保代码逻辑清晰易懂。这种方式值得在更多场景中推广。