单调栈学习笔记

单调栈算法笔记

单调栈

定义: 单调栈就是栈内元素递增或者单调递减的栈,并且只能在栈顶操作。单调栈的维护是O(n)的时间复杂度,所有元素只会进进栈一次

性质

  1. 单调栈里面的元素具有单调性;
  2. 元素加入栈前会把栈顶破坏单调性的元素删除;
  3. 使用单调栈可以找到元素向左遍历的第一个比他小的元素(单增栈),也可以找到元素向左遍历第一个比他大的元素(单减栈);
  4. 一般使用单调栈的题目具有以下的两点:
    • 离自己最近(栈的后进先出的性质)
    • 比自己大(小)、高(低);

注意:虽然称作是递增递减栈,但是实际存储的值并不是单调的,因为可以存坐标,只有坐标带入数组才是单调的。这样既可以存储数组的值,也可以存储数组下标。如下面的2,3,4例题。

例题

1、LeetCode 496. Next Greater Element I

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        vector<int> res(nums1.size(),-1);
        unordered_map<int,int>map;
        stack<int>stk;
        for(int i = 0 ; i < nums2.size(); i++){
            while(!stk.empty()&& nums2[i] > stk.top()){
                map[stk.top()] = nums2[i];
                stk.pop();
            }
            stk.push(nums2[i]);
    <span class="token punctuation">}</span>
    <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> nums1<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span>map<span class="token punctuation">[</span>nums1<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span>
            res<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> map<span class="token punctuation">[</span>nums1<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> res<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

2、LeetCode 42. Trapping Rain Water

class Solution {
public:
    int trap(vector<int>& height) {
        int res = 0;
        int n = height.size();
        if(n <= 2)
            return 0;
        stack<int>stk;
        for(int i = 0; i<n ; i++){
            while(!stk.empty() && height[stk.top()] < height[i]){
                int top = stk.top();
                stk.pop();
                if(stk.empty())
                    break;
                res += min(height[i] - height[top],height[stk.top()] - height[top])*(i - stk.top()-1);
            }
            stk.push(i);
        }
        return res;
    }
};

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

3、LeetCode 84. Largest Rectangle in Histogram

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        if(!heights.size()) return 0;
        int n = heights.size();
        heights.push_back(-1);
        int res = 0;
        stack<int>ss;
        for(int i = 0; i <= n ; i++){
            while(ss.size() && heights[ss.top()] > heights[i]){
                int top = ss.top();
                ss.pop();
                if(ss.size())
                   res = max(res, heights[top]*(i-ss.top()-1));
                else
                    res = max(res , heights[top]*i);
            }
            ss.push(i);       
        }
        return res;
    }
};

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

4、LeetCode 456. 132 Pattern

class Solution {
public:
    bool find132pattern(vector<int>& nums) {
        int n = nums.size();
        if(n < 3) return false;
        stack<int>ss;
        vector<int> right_min(n,INT_MAX);
        //此层循环找出nums[i]右边第一个比它小的数
        for(int i = n - 1; i >= 0 ; i--){
            while(ss.size() && nums[i] > nums[ss.top()]){
               right_min[i] = nums[ss.top()];
                ss.pop();
            }
            ss.push(i);
        }
        int min = nums[0];
        for(int i = 1; i < n ; i++){
            if(nums[i-1] < min ){
                min = nums[i-1];
            }
            if(nums[i] > right_min[i] && min < right_min[i])
                return true;
        }
        return false;
    }
};

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

其他使用单调栈的例题

  1. 仰视奶牛:找出每头奶牛最近仰视对象
  2. 发射站;发出的能量只被两边最近的且比它高的发射站接收

参考博客

  1. LeetCode Monotone Stack Summary 单调栈小结
  2. 单调栈的介绍以及一些基本性质
  3. 秦淮河单调栈讲义
                                </div><div><div></div></div>
            <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-60ecaf1f42.css" rel="stylesheet">
                            </div>

来自leetcode的单调栈题目推荐:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值