单调栈就是一种栈中数据大小顺序的栈,单调增/减栈
单调减栈:4,3,2,1
单调增栈:1,2,3,4
即:新数据符合单调性就弹入栈,不符合就不进站。
单调栈的一个特性:如单调增栈,栈中元素的左边一个元素就是原数据结构中第一小于该数据的元素(以自身为出发点左右查找)。同时下一个进栈的元素就是原数据结构中第一个大于该数据的元素。那么下一个进栈的元素在原数据结构中的前一个元素就是右边第一个小于改数据的元素。
例题1:最大矩形——递增单调栈
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
示例 :
输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10
题解思路:对于每一个柱子,它能够展开的矩形=高x(右边第一个比他矮的-左边第一个比他矮的),这里我们将数组扩展最后面添加一个0,这时可以使用单调递增栈,当满足条件时入栈,不满足条件时,先记下这个位置 i,然后栈顶的位置 top 就是我们要计算的矩形,先弹栈,则此时栈顶是目标左边第一个小于他的位置,不满足条件的 i 就是右边第一个小于他的位置。
注意:
- 需要扩展原数组,让最后一个元素为0。
- 在计算矩形面积时,需要判断栈是否为空,栈空,则目标左边第一个比他小的显然就是0了。
上图中例子的计算顺序是
i 0 3 2 5 4 1
面积 2 6 10 3 2 6
代码如下
public:
int largestRectangleArea(vector<int>& heights) {
heights.push_back(0);
int area = 0, n = heights.size();
stack <int> dec;
// 递增栈
for (int i = 0; i < n; i++) {
while(!dec.empty() && heights[i] <= heights[dec.top()]){
int high = heights[dec.top()];
int temp;
dec.pop();
if (dec.empty()){
temp = high * (i - 0);
}else{
temp = high * (i - (dec.top()+1));
}
cout << temp << endl;
if (temp > area){
area = temp;
}
}
dec.push(i);
}
return area;
}