单调栈
经典题: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)