LeetCode 84. 柱状图中最大的矩形

难度:困难。
标签:栈,数组。

没想到方法,看了标签,知道应该是单调栈,试了一下,结果是错的。单调栈这部分很不熟悉啊。
题解

枚举每一根柱子,以柱子 i i i的高度 h e i g h t i height_i heighti为高构成的矩形,则其宽由i左右两边第一个小于 h e i g h t i height_i heighti的柱子的位置决定的。因此找柱子 i i i的左右两边第一个小于其高度的柱子的位置。
l e f t [ i ] left[i] left[i]表示左边第一个小于 h e i g h t i height_i heighti的柱子的索引,用 r i g h t [ i ] right[i] right[i]表示右边第一个小于 h e i g h t i height_i heighti的柱子的索引。
这两个问题可以分别用单调栈来求。
然后,单调栈具体的操作没怎么看题解,自己想出来的。

正确解法:

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int n = heights.size();
        stack<int> stk;
        vector<int> left(n), right(n);
        for(int i = 0; i < n; ++i){
            while(!stk.empty() && heights[stk.top()] >= heights[i]){
                stk.pop();
            }
            if(stk.empty())left[i] = -1;
            else left[i] = stk.top();
            stk.push(i);
        }        
        stk = stack<int>();
        for(int i = n - 1; i >= 0; --i){
            while(!stk.empty() && heights[stk.top()] >= heights[i]){
                stk.pop();
            }
            if(stk.empty())right[i] = n;
            else right[i] = stk.top();
            stk.push(i);
        }
        int res = heights[0];
        for(int i = 0; i < n; i++){
            res = max(res, heights[i] * (right[i] - left[i] - 1));
        }
        return res;
    }
};

结果:
在这里插入图片描述

可以进一步进行优化,对栈遍历一次可以同时求解出left和right数组。
在求left过程中,对柱子 i i i进行出栈时,当前柱子即为 r i g h t [ i ] right[i] right[i]的结果。因此,一次即可求出两个结果。
需要提前将right数组用n进行初始化,这样,最终没有弹出栈的元素说明他们对应的right为n。

正确解法:

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int n = heights.size();
        stack<int> stk;
        vector<int> left(n), right(n, n);
        for(int i = 0; i < n; ++i){
            while(!stk.empty() && heights[stk.top()] >= heights[i]){
                right[stk.top()] = i; 
                stk.pop();
            }
            if(stk.empty())left[i] = -1;
            else left[i] = stk.top();
            stk.push(i);
        }
        int res = heights[0];
        for(int i = 0; i < n; i++){
            res = max(res, heights[i] * (right[i] - left[i] - 1));
        }
        return res;
    }
};

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值