[230527 lc84] 柱状图中最大的矩形

[230527 lc84] 柱状图中最大的矩形

一 题目

84. 柱状图中最大的矩形

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

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

示例 1:

img

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

示例 2:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ziV92sDJ-1685179820700)(null)]

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

提示:

  • 1 <= heights.length <=105

  • 0 <= heights[i] <= 104

二 整体思路

一道很典型的单调栈的题目。思路是利用单调栈找到每一个高度左边的第一个较小高度和右边的第一个较小高度,记录其下标,根据下标计算出对应高度所能达到的最大宽度,计算其面积。最后选取最大值返回。

三 关键点/重点/难点

对于单调栈来说,理解到找较小元素应该使用递增单调栈、找较大元素应该使用递减单调栈即可。找当前元素右边的第一个元素,使用正序遍历;找当前元素左边的第一个元素,使用倒序遍历。

这道题还有一个需要注意的点,在两个数组的初始化。左边元素数组应该初始化为 -1,右边元素数组应该初始化为 size。

四 代码分析

class Solution {
public:
    //应该是要找到,左边第一个小于自身的高度和右边第一个小于自身的高度
    //维护非严格递增单调栈:从栈底到栈顶是单调递增的
    int largestRectangleArea(vector<int>& heights) {
        stack<int> stk;
        vector<int> firstLeft(heights.size(), -1);
        vector<int> firstRight(heights.size(), heights.size());
        //正序遍历,构造firstRight
        for(int i = 0; i < heights.size(); ++i) {
            while(!stk.empty() && heights[stk.top()] > heights[i]) {
                int index = stk.top();
                stk.pop();
                firstRight[index] = i;
            }
            stk.push(i);
        }
        while(!stk.empty()) {
            stk.pop();
        }
        //倒序遍历,构造minRight
        for(int i = heights.size() - 1; i >= 0; --i) {
            while(!stk.empty() && heights[stk.top()] > heights[i]) {
                int index = stk.top();
                stk.pop();
                firstLeft[index] = i;
            }
            stk.push(i);
        }
        int result = 0;
        for(int i = 0; i < heights.size(); ++i) {
            int tmp = heights[i] * (firstRight[i] - firstLeft[i] - 1);
            result = max(tmp, result);
        }
        return result;
    }
};

(五)一题多解

单调栈太典型了,不想写了。

(六) 知识扩展

相关题目:

85. 最大矩形:求出以矩阵的每一行为底对应的柱状图,然后求每一个柱状图中的最大矩形面积,从中取最大值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值