2024字节青训营笔记(三)最大矩形面积问题 | 豆包MarsCode AI刷题

76 阅读4分钟

问题描述

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

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

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

即,R(k)R(k) 的值为这 kk 个相邻元素中的最小值乘以 kk。现在,小S希望你能帮他找出对于任意 kkR(k)R(k) 的最大值。

题目分析

问题理解

题目要求我们计算一个数组中任意 k 个相邻元素所能形成的最大矩形面积。具体来说,对于任意 k 个相邻元素,矩形的最大面积定义为这 k 个元素中的最小值乘以 k。我们需要找出对于所有可能的 k,这个最大面积的最大值。

数据结构选择

为了高效地解决这个问题,我们可以借鉴经典的“最大矩形面积”问题(通常使用单调栈来解决)。单调栈是一种非常适合处理“下一个更大/更小元素”问题的数据结构。在这里,我们可以利用单调栈来维护一个递增的高度序列,从而在 O(n) 的时间复杂度内计算出最大矩形面积。

算法步骤

  1. 初始化单调栈:使用一个栈来存储数组元素的索引,栈中的元素保持递增顺序。

  2. 遍历数组:对于数组中的每个元素,进行以下操作:

    • 如果当前元素小于栈顶元素对应的值,说明栈顶元素的高度不能再向右扩展,因此我们可以计算以栈顶元素为高度的矩形面积。
    • 计算面积时,宽度为当前元素索引与栈顶元素前一个元素索引的差值。
    • 更新最大面积。
    • 将当前元素的索引压入栈中。
  3. 处理栈中剩余元素:遍历结束后,栈中可能还剩下一些元素,这些元素的高度可以一直扩展到数组的末尾。我们依次弹出栈顶元素,计算以该元素为高度的矩形面积,并更新最大面积。

  4. 返回最大面积:最终,我们返回计算得到的最大面积。

详细分析

  1. 单调栈的作用

    • 单调栈可以帮助我们快速找到每个元素作为最小值时,能够形成的最大矩形的宽度。
    • 通过维护一个递增的栈,我们可以确保栈中的每个元素在弹出时,其右侧的元素都大于等于它,从而可以计算出以该元素为高度的矩形面积。
  2. 计算面积的逻辑

    • 当栈顶元素的高度大于当前元素时,栈顶元素的高度不能再向右扩展,因此我们可以计算以栈顶元素为高度的矩形面积。
    • 宽度为当前元素索引与栈顶元素前一个元素索引的差值。如果栈为空,说明栈顶元素的高度可以一直扩展到数组的起始位置。
  3. 时间复杂度

    • 每个元素最多入栈和出栈一次,因此时间复杂度为 O(n)
  4. 空间复杂度

    • 使用了一个栈来存储元素的索引,因此空间复杂度为 O(n)

代码实现思路

  1. 初始化栈和最大面积变量
  2. 遍历数组,对于每个元素:
    • 如果栈不为空且当前元素小于栈顶元素对应的值,弹出栈顶元素并计算面积。
    • 将当前元素的索引压入栈。
  3. 处理栈中剩余元素,计算面积并更新最大面积。
  4. 返回最大面积

使用单调栈可以高效地解决这个问题,并且在 O(n) 的时间复杂度内完成计算。

代码如下:

int solution(int n, std::vector<int>& array) {
    std::stack<int> stack;
    int max_area = 0;
    
    // 遍历数组
    for (int i = 0; i < n; ++i) {
        // 当栈不为空且当前元素小于栈顶元素对应的值时
        while (!stack.empty() && array[i] < array[stack.top()]) {
            // 弹出栈顶元素
            int height = array[stack.top()];
            stack.pop();
            // 计算宽度
            int width = stack.empty() ? i : i - stack.top() - 1;
            // 计算面积并更新最大面积
            max_area = std::max(max_area, height * width);
        }
        
        // 将当前元素的索引压入栈
        stack.push(i);
    }
    
    // 处理栈中剩余的元素
    while (!stack.empty()) {
        int height = array[stack.top()];
        stack.pop();
        int width = stack.empty() ? n : n - stack.top() - 1;
        max_area = std::max(max_area, height * width);
    }
    
    return max_area;
}