第55天-DP-第十章 单调栈 柱状图中的最大矩形

1. 柱状图中的最大矩阵

- 代码随想录链接

  • 这道题和接雨水有点像,但是接雨水是求两边的最大值来计算,本题是寻找两边最小的值来计算
  • 栈顶到栈底的排列顺序是从大到小的顺序

单调栈解法

class Solution {
public:

    // 寻找的是左右两边第一个小于 top 的值, 因此单调栈内  栈顶到栈底是从大大小排列的
    int largestRectangleArea(vector<int>& heights) {
        int result = 0;
        stack<int> st;

        // 数组头部和尾部加入 元素0        
        heights.insert(heights.begin(), 0);
        heights.insert(heights.end(), 0);
        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();
                    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;
    }
};

双指针解法

class Solution {
public:

    // 2.双指针解法
      int largestRectangleArea(vector<int>& heights) {
        int len = heights.size();
        // 1.使用数组存储每个元素对应的两边 第一个比当前元素小的下标
        vector<int> minLeft(len, 0);
        vector<int> minRight(len, 0);

        // 因为左右边界 都分别没有左边和右边第一个小的值,因此初始化的时候可以初始化为其他数
        minLeft[0] = -1;        // 防止下面的while死循环
        minRight[len-1] = len;  // 防止while死循环

        for(int i=1; i<len; i++){
            int t = i-1;                // 这里使用t为了寻找左边第一个小的值
            while(t >=0 && heights[t] >= heights[i]) t = minLeft[t];
            minLeft[i] = t;
        } 

        for(int i=len-2; i>=0; i--){
            int t = i+1;
            while(t<len && heights[t]>=heights[i]) t = minRight[t];
            minRight[i] = t;
        }

        // 求和
        int result = 0;
        for(int i=0; i<len; i++){
            int sum = heights[i] * (minRight[i] - minLeft[i] - 1);
            result = max(result, sum);
        }

        return result;

    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值