84. 柱状图中最大的矩形 (双指针、单调栈)

 

难度困难

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

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

 

示例 1:

输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10

示例 2:

输入: heights = [2,4]
输出: 4

 

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        heights = [0] + heights + [0]
        stack = []
        res = 0
        for i in range(len(heights)):
            cur = heights[i]
            while stack and cur < heights[stack[-1]]:
                top = stack.pop()
                area = heights[top] * (i-stack[-1]-1)  #不是i-top 212这种过不了 
                res = max(res,area)
            stack.append(i)
        return res 

 

 

 

 

 

 

 

 

 

中心扩散,找到当前以 hight[i] 为高,长度最长,然后算 面积。 

是以i 为中心,向左找第一个小于 heights[i] 的位置 left_i;向右找第一个小于于 heights[i] 的位置 right_i,即最大面积为 heights[i] * (right_i - left_i -1),如下图所示:

所以,我们的问题就变成如何找 right_i 和 left_i?

 

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int max_res = 0;
        int n = heights.size();
        for (int i = 0; i < n;i++) {
            int left_i = i;
            while (left_i >= 0 && heights[left_i] >= heights[i]) left_i--;
            int right_i = i;
            while (right_i <= n-1 && heights[right_i] >= heights[i]) right_i++;
            max_res = max(max_res,heights[i] * (right_i-left_i-1)); 
            //cout << heights[i]  << "  "  << left_i << "  " << right_i << endl;
        }
        return max_res;
    }
};

 

 

2 3 4 1 为例子,

234 入栈,到1 时,无法入栈。 需要将栈内大于1的元素弹出,此时,以右边界就找到了,就是1所在的索引,4的左边界就是把4弹出来,剩下的 top 就是3 所在的索引,继续弹,只到弹完,就相当于遍历了以 1为右边界,所有的面积。

 

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        
        // 两端补0, 不然24 这种 case 过不了、
        // 单调递增栈
        // 2,1,5,6,2,3   
        //  stk = 1 5 6  i = 2
        // 以6为高, 右边界是2,左边界是5
        heights.insert(heights.begin(),0);
        heights.push_back(0);
        int res = 0;
        int top = 0;
        stack<int> stk;
        for(int i = 0; i < heights.size(); i++) {
            while(!stk.empty() && heights[i] < heights[stk.top()]) {
                top = stk.top();
                stk.pop();
                res = max(res, heights[top]*(i-stk.top()-1));
            }
            stk.push(i);          
        }
        return res;
    }

 

 

 

 

 

 
 
posted @ 2022-04-14 10:01  乐乐章  阅读(86)  评论(0编辑  收藏  举报