算法学习day60

1.力扣84.柱状图中最大的矩形

1.1 题目描述

题目描述:

给定n个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为1。求在该柱状图中,能够勾勒出来的矩形的最大面积。

在这里插入图片描述
在这里插入图片描述

1.2 分析

单调栈:

核心思想:找每个柱子左右两边第一个小于该柱子的柱子。

由核心思想可以得出单调栈的顺序是(从栈头到栈底;从大到小)。

注:左边界、右边都是只输入的数组的位置。在入栈后可能会让人有所误解。比如说栈顶的下一个是左边界,准备入栈的是右边界

1.为什么要从栈头到栈底;从大到小?

答:当栈头到栈底从大到小的时候,是不是栈头当中间值,栈顶的下一位肯定比它小,当将要入栈的也比它小,是不是满足了核心思想了?

此时栈顶和栈顶的下一个元素以及将要入栈的三个元素就组成了我们要求的最大面积的高度和宽度。

2.为什么width = right - left -1 ?
在这里插入图片描述

3.开头为什么要加元素0?

答:如果数组本身是降序的,例如 [8,6,4,2],在 8 入栈后,6 开始与8 进行比较,此时我们得到 mid(8),rigt(6),但是得不到 left。

4.末尾为什么要加元素0?

答:如果数组本身就是升序的,例如[2,4,6,8],那么入栈之后 都是单调递减,一直都没有走 情况三 计算结果的哪一步,所以最后输出的就是0了。

1.3代码

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int result = 0;
        stack<int> st;                                           // 单调递增栈,存储heights数组中元素的下标
        heights.insert(heights.begin(), 0); // 在heights数组头部插入0
        heights.push_back(0);                       // 在heights数组尾部插入0
        st.push(0);                                               // 第一个元素入栈
        
        for (int i = 1; i < heights.size(); i++) {   // 从heights数组的第二个元素开始遍历
            if (heights[i] > heights[st.top()]) {   // 情况一:当前元素大于栈顶元素
                st.push(i);                                            // 当前元素入栈
            } else if (heights[i] == heights[st.top()]) {  // 情况二:当前元素等于栈顶元素
                st.pop();                                                             // 弹出栈顶元素(这个可以加,也可以不加,效果一样,思路不同)
                st.push(i);                                                         // 当前元素入栈
            } else {                                                                    // 情况三:当前元素小于栈顶元素
                while (!st.empty() && heights[i] < heights[st.top()]) { // 如果当前元素小于栈顶元素,就循环弹出栈顶元素
                    int mid = st.top();                                     // 弹出的栈顶元素为中间元素
                    st.pop();
                    if (!st.empty()) {                                       // 如果栈不为空
                        int left = st.top();                                // 左边界为左侧第一个比中间元素小的元素
                        int right = i;                                          // 右边界为右侧第一个比中间元素小的元素
                        int w = right - left - 1;                       // 计算矩形的宽
                        int h = heights[mid];                       // 矩形的高为中间元素的高度
                        result = max(result, w * h);          // 更新结果
                    }
                }
                st.push(i);                                                  // 当前元素入栈
            }
        }
        
        return result;                                                  // 返回结果
    }
};

2.参考资料

[代码随想录]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值