1.目录
2.单调栈作用:
以o(n)的时间复杂度,找到数组内所有元素左边(右边)第一个比自己大(小)的元素(或下标)
1.单调栈已经做了五道题了,别的都不多说,单调栈就一个作用,遇到需要这个作用的都想到单调栈,以o(n)的时间复杂度,找到数组内所有元素左边(右边)第一个比自己大(小)的元素(或下标)
2.每日温度不说了就是找右边第一个比自己大的元素
3.下一个更大元素I 下一个更大元素Ⅱ 这还用说吗,直接就是找右边第一个比自己大的元素+一点点绕弯子
3.接雨水,其实是找左右最大的元素,但是由于单调栈只会找第一个大的元素,所以我们要想从问题层面转化问题,那就是按行求雨水,然后就可以使用单调栈的功能了。
4.柱状图的最大矩形,和接雨水很像,接雨水时一个凹然后求值,这道题是一个凸求值,几乎是一样的!
5.所以总结来总结去,单调栈就一个功能,以o(n)的时间复杂度,找到数组内所有元素左边(右边)第一个比自己大(小)的元素(或下标),如果题目不能直接使用这个功能完成,就像接雨水和柱状图,那就从问题层面想办法通过转化使用上这个单调栈的功能!
2.单调栈代码示例:
简介版:
class Solution2 {
public:
int trap(vector<int>& height) {
//存着下标,计算的时候用下标对应的柱子高度
stack<int> stack;
int sum=0;
//构建单调栈
stack.push(0);
for(int i=1;i<height.size();i++){
while(stack.empty()== false&&height[stack.top()]<height[i]){
int mid=stack.top();
stack.pop();
if(stack.empty()== false){
int left=height[stack.top()];
int right=height[i];
int h=min(left,right)-height[mid];
int width=i-stack.top()-1;
sum+=h*width;
}
}
stack.push(i);
}
return sum;
}
};
逻辑清晰版:
class Solution1 {
public:
int trap(vector<int>& height) {
//存着下标,计算的时候用下标对应的柱子高度
stack<int> stack;
int sum=0;
//构建单调栈
stack.push(0);
for(int i=1;i<height.size();i++){
//1.
if(height[stack.top()]>height[i]){
stack.push(i);
continue;
}
//2.
if(height[stack.top()]==height[i]){
//其实这一句可以不加,效果是一样的,但处理相同的情况的思路却变了。
stack.pop();
stack.push(i);
continue;
}
//3.
if(height[stack.top()]<height[i]){
while(stack.empty()== false&&height[stack.top()]<height[i]){
int mid=stack.top();
stack.pop();
if(stack.empty()== false){
int left=height[stack.top()];
int right=height[i];
int h=min(left,right)-height[mid];
int width=i-stack.top()-1;
sum+=h*width;
}
}
stack.push(i);
}
}
return sum;
}
};