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

64 阅读3分钟

题目链接:www.marscode.cn/practice/8e…

image.png

如果暴力求解的话,需要遍历区间左右断点,而后在区间内寻找最小值,这个时间复杂度是O(n3)O(n^3)的,显然是不能接受的。

再进一步思考,寻找区间最小值可以用线段树来做,可以把时间复杂度降到O(n2log(n))O(n^2log(n))

那有没有可能用O(n)O(n)的时间复杂度解决呢,其实是可以的,我们仔细分析一下,对于每个位置,我们找到它左边第一个小于它的地方和右边第一个小于它的地方,这一段的高度取决于最小的当前高度,宽度就是两个断点的间距,这样遍历每一个元素即可求出最大的矩形面积。

那要找到每个元素,距离它最近的小于它元素的数据结构就是单调栈了

这段代码的目的是计算数组中任意连续子数组所能形成的最大矩形面积。具体来说,对于每个元素,代码尝试找到以该元素为最小高度的最大矩形面积。以下是代码的详细思路解读:

1. 数据结构选择

  • 栈(stack<int> :用于辅助计算每个元素的左右边界。
  • 两个数组(vector<int> l 和 vector<int> r :分别存储每个元素的左边界和右边界。

2. 算法步骤

2.1 计算左边界

  • 遍历数组 A,对于每个元素 A[i]

    • 使用栈来维护一个递增序列的索引。
    • 如果栈顶元素对应的值大于等于当前元素 A[i],则弹出栈顶元素,直到栈为空或栈顶元素对应的值小于当前元素。
    • 如果栈为空,说明当前元素左边没有比它小的元素,左边界为 -1
    • 否则,左边界为栈顶元素的索引。
    • 将当前元素的索引压入栈中。

2.2 计算右边界

  • 从右向左遍历数组 A,对于每个元素 A[i]

    • 使用栈来维护一个递增序列的索引。
    • 如果栈顶元素对应的值大于等于当前元素 A[i],则弹出栈顶元素,直到栈为空或栈顶元素对应的值小于当前元素。
    • 如果栈为空,说明当前元素右边没有比它小的元素,右边界为 -1
    • 否则,右边界为栈顶元素的索引。
    • 将当前元素的索引压入栈中。

2.3 计算最大矩形面积

  • 遍历数组 A,对于每个元素 A[i]

    • 计算以 A[i] 为最小高度的矩形的宽度:

      • 左边界 L 为 i - l[i] - 1,如果 l[i] 为 -1,则 L 为 i
      • 右边界 R 为 r[i] - i - 1,如果 r[i] 为 -1,则 R 为 n - i - 1
    • 计算矩形的面积为 (L + R + 1) * A[i]

    • 更新最大面积 res

3. 结果返回

  • 返回计算得到的最大矩形面积 res

4. 测试用例

  • 在 main 函数中,添加了一个测试用例 A_case1 = {5, 4, 3, 2, 1, 6},并验证结果是否为 9
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
using namespace std;

int solution(int n, std::vector<int> A) {
    // Edit your code here
    stack<int> stk;
    vector<int> l(n + 1, 0), r(n + 1, 0);
    for (int i = 0; i < n; i++) {
        int x = A[i];
        while(!stk.empty() && A[stk.top()] >= x) stk.pop();
        if (stk.empty()) l[i] = -1;
        else {
            l[i] = stk.top();
        }
        stk.push(i);
    }
    while (!stk.empty()) stk.pop();
    for (int i = n - 1; i >= 0; i--) {
        int x = A[i];
        while (!stk.empty() && A[stk.top()] >= x) stk.pop();
        if (stk.empty()) r[i] = -1;
        else {
            r[i] = stk.top();
        }
        stk.push(i);
    }

    // for (int i = 0; i < n; i++) {
    //     cout << "l: " << l[i] << " " << "r: " << r[i] << endl;
    // }

    int res = 0;
    for (int i = 0; i < n; i++) {
        int L = 0, R = 0;
        if (l[i] == -1) L = i;
        else L = i - l[i] - 1;
        if (r[i] == -1) R = n - i - 1;
        else R = r[i] - i - 1;

        res = max(res, (L + R + 1) * A[i]);
    }
    return res;
}

int main() {
    // Add your test cases here
    std::vector<int> A_case1 = std::vector<int>{5,4,3,2,1,6};
    std::cout << (solution(6, A_case1) == 9) << std::endl;
    return 0;
}

image.png