【leetcode】84 柱状图中最大的矩形(动态规划,栈)

题目链接:https://leetcode-cn.com/problems/largest-rectangle-in-histogram/

题目描述

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

在这里插入图片描述

以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。

在这里插入图片描述

图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。

思路

1 暴力

i位置作为左边界,j遍历i~n得到(i,j)这个区间的最小高度,(j-i+1)*minHeight得到以i作为左端点,j作为右端点的最大矩形面积。

复杂度分析

时间复杂度: O ( n 2 ) O(n^2) 。 需要枚举所有可能的柱子对。
空间复杂度: O ( 1 ) O(1) 。不需要额外的空间。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        if (heights.empty()) return 0;
        int maxArea = 0;
        for (int i = 0; i < heights.size(); ++i) {
            int minHeight = heights[i];
            for (int j = i; j < heights.size() && heights[j]!=0; ++j){
                minHeight = min(minHeight, heights[j]);
                maxArea = max(maxArea,minHeight*(j-i+1));
            }
        }
        return maxArea;
    }
};

很遗憾,超时了=。=!
在这里插入图片描述

扫描二维码关注公众号,回复: 6510585 查看本文章

2 栈

在这种方法中,我们维护一个栈。一开始,我们把 -1 放进栈的顶部来表示开始。初始化时,按照从左到右的顺序,我们不断将柱子的序号放进栈中,直到遇到相邻柱子呈下降关系,也就是 a[i-1] > a[i]a[i−1]>a[i] 。现在,我们开始将栈中的序号弹出,直到遇到 stack[j] 满足a[stack[j]]≤a[i] 。每次我们弹出下标时,我们用弹出元素作为高形成的最大面积矩形的宽是当前元素与 stack[top-1]之间的那些柱子。也就是当我们弹出 stack[top] 时,记当前元素在原数组中的下标为 i ,当前弹出元素为高的最大矩形面积为:

(i−stack[top−1]−1)×a[stack[top]].

更进一步,当我们到达数组的尾部时,我们将栈中剩余元素全部弹出栈。在弹出每一个元素是,我们用下面的式子来求面积: (stack[top]−stack[top−1])×a[stack[top]],其中,stack[top]表示刚刚被弹出的元素。因此,我们可以通过每次比较新计算的矩形面积来获得最大的矩形面积。

复杂度分析
时间复杂度: O ( n ) O(n) 。 n个数字每个会被压栈弹栈各一次。
空间复杂度: O ( n ) O(n) 。用来存放栈中元素。

/*
 * 单调栈
 * 时间复杂度O(n) 空间复杂度O(n)
 */
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        if (heights.empty()) return 0;
        stack<int> s;   // 存储序号
        s.push(-1);
        int maxArea = 0;
        for (int i = 0; i < heights.size(); ++i) {
            // 下降时pop
            while (s.top() != -1 && heights[s.top()] >= heights[i]){
                int tmp = s.top();
                s.pop();
                // 用弹出元素作为高形成的最大面积矩形,其宽是当前元素与s[top-1]之间的那些柱子
                maxArea = max(maxArea, heights[tmp] * (i-s.top() - 1));
            }
            s.push(i);
        }
        while (s.top()!= -1){
            int tmp = s.top();
            s.pop();
            int curArea = heights[tmp] * (heights.size() - s.top() - 1);
            maxArea = max(maxArea, curArea);
        }

        return maxArea;
    }
};

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zjwreal/article/details/91477800