笔者在做leecode的题(求柱形的最大面积)时,接触到了单调栈这一数据结构,经过研究发现,单调栈是一个比较简单的数据结构,但是要灵活运用却十分不简单。
单调栈定义
单调递增栈:数据出栈的序列为单调递增序列
单调递减栈:数据出栈的序列为单调递减的序列
单调栈的应用
1.视野总和
描述:有n个人站队,所有的人全部向右看,个子高的可以看到个子低的发型,给出每个人的身高,问所有人能看到其他人发型的总和是多少。
例子:输入:4 3 7 1 输出:2
解释:个子为4的可以看到个子为3的发型,个子为7的可以看到个子为1的发型。
思路:题目实际可以转化为找当前数字向右查找的第一个大于它之间的数字有多少个数字,然后将结果累计即为结果。
1.设置一个单调递增的栈(出栈序列单调递增)
2.当遇到大于栈顶的元素时,开始更新之前不高于当前人所能看到的值。
这种情况下得在原始序列push一个INT_MAX。使全部元素能够出栈。
2.柱状图中的最大矩形面积
https://leetcode-cn.com/problems/largest-rectangle-in-histogram/
思路:当前的数字可以向两边扩展,遇到比自己大的就扩展,小的就停止。然后用自己的高度乘以扩展的宽度就是最大面积。
因为栈中序列是递增的,所以往左不可扩展,当碰到比栈顶元素小的数据的时候就是扩展的右边界。
读者可以对照代码来理解。
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
stack<int>s;
int ans = 0;
heights.push_back(-1);
int len = heights.size();
for (int i = 0; i < len; ++i) {
while (!s.empty() && heights[i] < heights[s.top()]) {
int t = s.top();
s.pop();
if (s.empty()) {
ans = max(ans, heights[t] * i);
}
else ans = max(ans, heights[t] * (i - s.top() - 1));
}
s.push(i);
}
return ans;
}
};
3.求最大区间
描述:给出一组数组,求一区间,使得区间元素和乘以区间最小值最大,结果要求给出这个最大值和区间的左右端点。
输入:3 1 6 4 5 2
输出:60
3 5
将[3,5] (6+4+5)这段区间相加,将和与区间内最小元素相乘获得最大数字60。
思路:应使用单调递减栈,建议参考博客https://blog.csdn.net/u010325193/article/details/85389722