摘录于lucky52529
从名字上就听的出来,单调栈中存放的数据应该是有序的,所以单调栈也分为单调递增栈和单调递减栈
举个例子:
现在有一组数10,3,7,4,12。从左到右依次入栈,则如果栈为空或入栈元素值小于栈顶元素值,则入栈;否则,如果入栈则会破坏栈的单调性,则需要把比入栈元素小的元素全部出栈。单调递减的栈反之。
再举一个通俗的例子(摘自Grandyang):比如有一天,某家店在发 free food,很多人在排队,于是你也赶过去凑热闹。但是由于来晚了,队伍已经很长了,想着不然就插个队啥的。但发现排在队伍最前面的都是一些有纹身的大佬,惹不起,只能赞美道,小猪佩奇身上纹,来世还做社会人。于是往队伍后面走,发现是一群小屁孩,直接全部撵走,然后排在了社会大佬们的后面。那么这就是一个单调递减的栈,按实力递减。由于栈元素是后进先出的,所以上面的例子正确的检查顺序应该是从队尾往前遍历,小屁孩都撵走,直到遇到大佬停止,然后排在大佬后面(假设这个队列已经事先按实力递减排好了)。
明白了单调栈的加入元素的过程后,我们来看看它的性质,以及为啥要用单调栈。单调栈的一大优势就是线性的时间复杂度,所有的元素只会进栈一次,而且一旦出栈后就不会再进来了。
(摘自https://www.acwing.com/user/myspace/solution/index/leetcode/21/2/)
https://leetcode.com/problems/largest-rectangle-in-histogram/
Input: [2,1,5,6,2,3]
Output: 10
解释:如下图显示的最大矩形位置
class Solution {
public:
int largestRectangleArea(vector& heights) {
int n = heights.size(), ans = 0;
heights.push_back(-1);
// 为了算法书写方便,在数组末尾添加高度 -1
// 这会使得栈中所有数字在最后出栈。
stack st;
for (int i = 0; i <= n; i++) {
while (!st.empty() && heights[i] < heights[st.top()]) {
int cur = st.top();
st.pop();
if (st.empty())
ans = max(ans, heights[cur] * i);
else
ans = max(ans, heights[cur]
* (i - st.top() - 1));
}
st.push(i);
}
return ans;
}
};
https://leetcode.com/problems/trapping-rain-water/description/
给定n个非负整数,代表一个高度地图,每个位置的矩形条宽度为1,计算该图形能装下多少单位的水。
样例
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
class Solution {
public:
int trap(vector& height) {
int n = height.size(), ans = 0;
stack st;
for (int i = 0; i < n; i++) {
while (!st.empty() && height[st.top()] < height[i]) {
int top = st.top();
st.pop();
if (st.empty()) break;
ans += (i - st.top() - 1) * (min(height[st.top()], height[i]) - height[top]);
}
st.push(i);
}
return ans;
}
};
https://leetcode.com/problems/maximal-rectangle
给定一个二维的矩阵,矩阵只包含0和1。找到最大的只包含1的矩形,返回它的面积。
输入:
[
["1","0","1","0","0"],
["1","0","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"]
]
输出:6
class Solution {
public:
int maximalRectangle(vector>& matrix) {
int n = matrix.size(), m, ans = 0;
if (n == 0)
return 0;
m = matrix[0].size();
vector heights(m + 1, 0);
heights[m] = -1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++)
if (matrix[i][j] == '0')
heights[j] = 0;
else
heights[j]++;
stack st;
for (int j = 0; j <= m; j++) {
while (!st.empty() && heights[j] < heights[st.top()]) {
int cur = st.top();
st.pop();
if (st.empty())
ans = max(ans, heights[cur] * j);
else
ans = max(ans, heights[cur] * (j - st.top() - 1));
}
st.push(j);
}
}
return ans;
}
};