【每日一题】柱状图中最大的矩形

发布于:2023-01-19 ⋅ 阅读:(213) ⋅ 点赞:(0)

在这里插入图片描述

题目描述


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

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

示例 1:

在这里插入图片描述

输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10
示例 2:
在这里插入图片描述

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

提示:

1 <= heights.length <=105
0 <= heights[i] <= 104

题解


暴力


部分测试用例通不过,因为O(N^2)的时间复杂度。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        //挨个遍历
        int maxNum = 0;
        for(int i = 0;i < heights.size();++i)
        {
            if(heights[i] == 0) continue;

            int result = 0;
            int height = heights[i];
            for(int j = 0;j < heights.size();++j)
            {
                if(heights[j] >= height)
                {
                    //取height周围的举行
                    result += height;
                }
                else
                {
                    //若遇到矮的则结束计算
                    maxNum = max(maxNum,result);
                    result = 0;//往后需要重新计算result
                    continue;
                }
            }
            maxNum = max(maxNum,result);
        }

        return maxNum;
    }
};

单调栈


每次遍历到heights[i]的时候,实际上我们已经能够判断出前面以heights[0~i-1]当中有哪些点为高的已经不满足了,此时我们可以通过栈来存取先前点,若是碰到矮的,我们就可以通过i - 栈顶的下标 O(1)操作确认宽度,且高度就是栈顶的高度。此时栈只需要添加i下标元素时依旧是单调递增即可。
栈当中存下标
处理可以分成两部:

  • 第一次遍历的时候右边界是确定好的,所以可以直接求,左边界是pop后top的结果,因为前面可能出现更高的但是已经出栈的元素。
  • 当遍历完后,栈不为空,此时右边界就是heights.size(),左边界就是栈顶的元素,最后一个元素是宽度是heights.size()
class Solution {
public:
    int largestRectangleArea(vector<int> heights) {
        //单调栈处理
        stack<int> st;
        int result = 0;
        //单调栈只存储下标,减少需要向前找宽度的过程
        for (int i = 0; i < heights.size(); ++i)
        {
            if (st.empty())
            {
                st.push(i);
            }
            else
            {
                if (heights[i] >= heights[st.top()])
                {
                    st.push(i);
                }
                else
                {
                    //这里相当于后面碰到更矮的,所以只用算前面的。
                    //表示当前元素比栈顶小,需要出栈顶元素 
                    //注意这里的左右边界的判定,左边界是pop后top的结果,右边界就是i
                    while (!st.empty() && heights[st.top()] > heights[i])
                    {
                        int tmp = 0;//临时面积
                        int cur = st.top();
                        st.pop();
                        int pre = -1;
                        if (!st.empty())
                        {
                            pre = st.top();
                        }

                        tmp += (i - pre - 1 ) * heights[cur];
                        result = max(result, tmp);
                    }
                    st.push(i);//这个元素也需要入栈
                }
            }
        }
        while (!st.empty())
        {
            int cur = st.top();
            st.pop();
            if (st.empty())
            {
                //只剩下最后一个元素
                int tmp = heights[cur] * heights.size();
                result = max(result, tmp);
            }
            else
            {
                //看前面元素在哪,就可以找到宽度
                int pre = st.top();
                //此时右边界不是cur,而是最右边
                int tmp = (heights.size() - 1 - pre) * heights[cur];
                result = max(tmp, result);
            }
        }
        return result;
    }
};



end

  • 喜欢就收藏
  • 认同就点赞
  • 支持就关注
  • 疑问就评论
本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到