单调栈问题

单调栈

经典题:leetcode84,leetcode42,leetcode768
单调递增栈可以找到左起第一个比当前数字小的元素。比如数组 [2 1 4 6 5],刚开始2入栈,数字1入栈的时候,发现栈顶元素2比较大,将2移出栈,此时1入栈。那么2和1都没左起比自身小的数字。然后数字4入栈的时候,栈顶元素1小于4,于是1就是4左起第一个小的数字。此时栈里有1和4,然后数字6入栈的时候,栈顶元素4小于6,于是4就是6左起第一个小的数字。此时栈里有1,4,6,然后数字5入栈的时候,栈顶元素6大于5,将6移除,此时新的栈顶元素4小于5,那么4就是5左起的第一个小的数字,最终栈内数字为 1,4,5。
单调递减栈可以找到左起第一个比当前数字大的元素。

以leetcode 42收集雨水为例子
Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.
在这里插入图片描述

可以发现,只有中间低两边高才会装下雨水。可以使用一个单调递减栈,将递减的边界存进去,一旦发现当前的数字大于栈顶元素了,那么就有可能会有能装水的地方产生。此时我们当前的数字是右边界,我们从栈中至少需要有两个数字,才能形成一个坑槽,先取出的那个最小的数字,就是坑槽的最低点,再次取出的数字就是左边界,我们比较左右边界,取其中较小的值为装水的边界,然后此高度减去水槽最低点的高度,乘以左右边界间的距离就是装水量了。注意:单调栈中不能放高度,而是需要放坐标

 int trap(vector<int>& height) {
        stack<int> st;
        int i = 0, res = 0, n = height.size();
        while (i < n) {
            if (st.empty() || height[i] <= height[st.top()]) {
                st.push(i++);
            } else {
                int t = st.top(); st.pop();
                if (st.empty()) continue;
                res += (min(height[i], height[st.top()]) - height[t]) * (i - st.top() - 1);
            }
        }
        return res;
    }

leetcode 84 求直方图中的最大矩阵
在这里插入图片描述

int largestRectangleArea(vector<int>& heights) {
        int res = 0;
        stack<int> st;
        heights.push_back(0);
        for (int i = 0; i < heights.size(); ++i) {
            while (!st.empty() && heights[st.top()] >= heights[i]) {
                int cur = st.top(); st.pop();
                res = max(res, heights[cur] * (st.empty() ? i : (i - st.top() - 1)));
            }
            st.push(i);
        }
        return res;
    }

2019 9 .1 腾讯笔试第四题
在这里插入图片描述在这里插入图片描述在这里插入图片描述
单调栈

#include <iostream>
#include <vector>
#include <stdio.h>
#include <algorithm>
#include <stack>

using namespace std;
int largestRectangleArea(vector<int>& heights, vector<int>& num) {
	int res = 0;
	stack<int> st;
	heights.push_back(0);
	for (int i = 0; i < heights.size(); ++i) {
		while (!st.empty() && heights[st.top()] >= heights[i]) {
		 
			int cur = st.top(); st.pop();
			
			
			res = max(res, heights[cur] * (st.empty() ? num[i] : (num[i] - num[st.top() + 1])));
		}
		st.push(i);
	}
	return res;
}


int main()
{
	vector<int> h = { 1,2,3,4,5 };
	vector<int> num;
	for (int i = 0; i < h.size() + 1; i++)
	{
		if (i == 0)
			num.push_back(0);
		else
			num.push_back(h[i - 1] + num[i - 1]);

	}

	cout << largestRectangleArea(h, num);
	return 0;
	system("pause");




}

参考资料https://www.cnblogs.com/grandyang/p/8887985.html)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值