_52LeetCode代码随想录算法训练营第五十二天-单调栈 | 84.柱状图中最大的矩形

2023年2月8日23点23分 代码随想录一刷 完结撒花 开心子

_52LeetCode代码随想录算法训练营第五十二天-单调栈 | 84.柱状图中最大的矩形

题目列表

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

84.柱状图中最大的矩形

代码随想录地址:https://programmercarl.com/0084.%E6%9F%B1%E7%8A%B6%E5%9B%BE%E4%B8%AD%E6%9C%80%E5%A4%A7%E7%9A%84%E7%9F%A9%E5%BD%A2.html

题目

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

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

示例 1:

_52LeetCode代码随想录算法训练营第五十二天-单调栈 | 84.柱状图中最大的矩形_第1张图片

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

示例 2:

_52LeetCode代码随想录算法训练营第五十二天-单调栈 | 84.柱状图中最大的矩形_第2张图片

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

提示:

  • 1 <= heights.length <= 1 0 5 10^5 105
  • 0 <= heights[i] <= 1 0 4 10^4 104

思路

柱子彼此相邻,宽度都为1,高度各不相同。对于当前考察的柱子来说,它所能勾勒出的矩形面积是由其左边柱子和右边柱子的高度共同决定的。

如果其左边柱子的高度大于等于当前柱子的高度,则可以向左侧扩张,直到左边柱子高度小于当前柱子高度或左边再无其它柱子;同样的,如果其右边柱子的高度大于等于当前柱子的高度,则可以向右侧扩张,直到右边柱子高度小于等于当前柱子高度或右边再无其它柱子。

这时,就可以计算出以当前柱子高度为高,左右柱子间距离为宽的矩形面积。

作者:hardcore-aryabhata
链接:https://leetcode.cn/problems/largest-rectangle-in-histogram/solution/dong-hua-yan-shi-dan-diao-zhan-84zhu-zhu-03w3/

双指针解法

就是说,对于每个柱子,找到其最远能扩张的左柱子,和最远能扩张的右柱子,然后以当前柱子为高,左到右为宽,求得面积。

单调栈解法

栈头(元素从栈头弹出)到栈底的顺序为从大到小。

栈顶元素是高度最大的元素,栈顶的下一个元素是左边能扩展到的下一个元素,当前元素是右边能扩展到的下一个元素。

三种情况:

栈顶元素一直是最高的元素。

  • 情况一:当前遍历的元素heights[i]小于栈顶元素heights[st.top()]的情况

就求面积并更新max面积。考虑出栈嘻嘻。

  • 情况二:当前遍历的元素heights[i]等于栈顶元素heights[st.top()]的情况

将当前元素入栈。

  • 情况三:当前遍历的元素heights[i]大于栈顶元素heights[st.top()]的情况

将当前元素入栈。

代码

双指针解法

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int sum = 0;
        for (int i = 0; i < heights.size(); i++) {
            int left = i;
            int right = i;
            for (; left >= 0; left--) {
                if (heights[left] < heights[i]) break;
            }
            for (; right < heights.size(); right++) {
                if (heights[right] < heights[i]) break;
            }
            int w = right - left - 1;
            int h = heights[i];
            sum = max(sum, w * h);
        }
        return sum;
    }
};

单调栈解法

/*
 * @lc app=leetcode.cn id=84 lang=cpp
 *
 * [84] 柱状图中最大的矩形
 */

// @lc code=start
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        //数组头部和尾部都加入0是为了处理原始height的第一个元素和最后一个元素作为高的情况
        heights.insert(heights.begin(), 0);
        heights.push_back(0);
        int res = 0;
        stack<int> st;
        st.push(0);//初始插入第一个元素的下标
        for(int i = 1; i < heights.size(); i++)
        {
            //三种情况
            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();
                    int high = heights[mid];
                    int length = i - st.top() - 1;
                    res = max(res, high * length);
                }
                st.push(i);
            }
        }
        return res;
    }
};
// @lc code=end

你可能感兴趣的:(Algorithms,算法,c++,leetcode)