LeetCode第 84 题:柱状图中最大的矩形(C++)

84. 柱状图中最大的矩形 - 力扣(LeetCode)
在这里插入图片描述
单调栈求矩形面积系列:
LeetCode第 84 题:柱状图中最大的矩形(C++)_zj-CSDN博客
LeetCode第 85 题:最大矩形(C++)_zj-CSDN博客
LeetCode第 221 题:最大正方形(C++)_zj-CSDN博客

暴力法

考虑暴力法:遍历每根柱子,以当前柱子 i 的高度作为矩形的高,那么矩形宽度的左边界即为向左找到第一个高度小于当前柱体 i 的柱体,右边界即为向右找到第一个高度小于当前柱体 i 的柱体。对于每个柱子都计算一遍以当前柱子作为高的矩形面积,最终比较出最大的矩形面积:

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int res = 0, n = heights.size();
        // 遍历每个柱子,以当前柱子的高度作为矩形的高 h,
        // 从当前柱子向左右遍历,找到矩形的宽度 w。
        for (int i = 0; i < n; i++) {
            int w = 1, h = heights[i], j = i-1;//宽,高
            //相当于以当前值为矩形高度,尽量向两边扩展宽
            while (j >= 0 && heights[j--] >= h)	w++;//宽向左增加1
            j = i+1;
            while (j < n && heights[j++] >= h)	w++;//宽向右增加1
            res = max(res, w * h);
        }
        return res;
    }
};

最后的用例超时了,但是至少证明方法思路是对的。

单调栈

单调栈的思路,细节很多,画画图更好理解:暴力解法、栈(单调栈、哨兵技巧) - 柱状图中最大的矩形 - 力扣(LeetCode)

class Solution {
public:
    int largestRectangleArea(vector<int>& heights){
        int res = 0;
        stack<int> stk;//单调栈,存储的是下标
        //首尾添加哨兵
        heights.insert(heights.begin(), 0);
        heights.push_back(0);
        for (int i = 0; i < heights.size(); i++){
            while (!stk.empty() && heights[stk.top()] > heights[i]){//一定是while循环
                int height = heights[stk.top()];//矩形高
                stk.pop();
                int width = i - stk.top() - 1;//矩形宽(建议画图进行辅助理解,这儿很容易出错)
                res = max(res, height*width);
            }
            stk.push(i);
        }
        return res;
    }
};

如果不适用哨兵(不在前后插入0):

class Solution {
public:
    int largestRectangleArea(vector<int>& heights){
        int res = 0;
        stack<int> stk;//单调栈,存储的是下标
        stk.push(-1);//为了方便计算(其实也算是哨兵)
        for (int i = 0; i < heights.size(); i++){
            while (stk.top() != -1 && heights[stk.top()] > heights[i]){
                int height = heights[stk.top()];//矩形高
                stk.pop();
                int width = i - stk.top() - 1;//矩形宽
                res = max(res, height*width);
            }
            stk.push(i);
        }
        while(stk.top() != -1){
            int height = heights[stk.top()];
            stk.pop();
            int width = heights.size() - stk.top() - 1;
            res = max(res, height*width);
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值