专题复习一:单调栈

栈(stack)是一种特殊的数据结构,但也是一种容易理解的数据结构,它的特点就是先进后出,生活中有很多栈的例子,比如装乒乓球的直筒,最先进入的球到达桶底,然后一个一个进入,最后进入的球在出桶的时候是第一出来,最先进去的是最后一个出来。本文所提到的单调栈其实就是在普通栈的基础上加上了单调的特性,栈内元素保持单调递增或者单调递减的特性。

一、 基础案例

(1)数组内下一个更大的元素

给你一个数组nums,请返回一个等长的数组,这个等长数组对应于nums的相同位置存储着下一个更大元素,如果没有更大元素,请存储数值-1。假设nums的每个元素都不为负数。

案例:
比如输入数组为nums = [2,1,3,4,2],那么返回数组[3,3,4,-1,-1]

解释:
数组nums的第一个元素2的下一个更大元素是3,第二个元素1的下一个更大元素是3,第三个元素3的下一个更大元素是4,第四个元素4没有下一个更大元素,第五个元素2同样没有下一个更大元素。

思路:利用单调栈 建立栈stack<int> a; 用来存储下一个最大的元素。

从末尾向前遍历nums,当 a不为空,且 nums[i] >= a.top()  要压出栈顶的元素,直至 a为空或者 nums[i] < a.top(),

class Solution {
public:
    vector<int> nextGreaterNum(vector<int>& nums) {    
    int size = nums.size();
    stack<int> a;
    vector<int> res(size, 0);
    for(int i = size - 1; i >= 0; i--)
    {
        while(!a.empty()&&nums[i] >= a.top()) //a 的栈顶元素,即为当前nums[i] 后面第一个大于nums[i]的元素
        {
            a.pop();
        }
        res[i] = a.empty()? -1: a.top();
        a.push(nums[i]);
    }
    return res;
    
    }
};

(2) 单调栈的变形利用

此时,单调栈存储的是 下一个最大值的索引值

739. 每日温度 

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        int size = temperatures.size();
        stack<int> a; //此时,单调栈存储的是 下一个最大值的索引值
        vector<int> res(size, 0);
        for(int i = size - 1; i >= 0; i--)
        {
            while(!a.empty() && temperatures[i]>= temperatures[a.top()])
            {
                a.pop();
            }
            res[i] = a.empty()? 0 : a.top() - i;
            a.push(i);
        }
        return res;
    }
};

leetcode 496. 下一个更大元素 I

本题中,是两个数组,其中nums1是nums2的子数组,因此,首先计算出nums2中每一个元素的后一个最大元素,在利用map将对应关系保存,然后,在根据nums1数组中元素去找对应的后一个最大元素。

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {

        stack<int> a;
        unordered_map<int, int> maptemp;//存在nums2中每一个元素与后一个较大元素的对应关系

        for(int i = nums2.size() - 1; i >= 0; i--)
        {
            while(!a.empty() && nums2[i] >= a.top())
            {
                a.pop();
            }
            maptemp[nums2[i]] = a.empty()? -1 : a.top();
            a.push(nums2[i]);
        }
        vector<int> res(nums1.size(), 0);
        for(int j = 0; j < nums1.size(); j++)
        {
            res[j] = maptemp[nums1[j]];
        }
        return res;

    }
};

503. 下一个更大元素 II

本题的难点是:循环数组。在数据结构中,利用模运算模拟模拟环状数据结构。

因为要考虑环状数组,首先想到的是构建新的nums是原nums中元素可以循环起来,但是这样会耗费空间。用取模操作。

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        int size = nums.size();
        stack<int> a;
        vector<int> res(size, 0);
        for(int i = (2*size - 1); i >= 0; i--)//此时相当于将nums边长构成循环数组
        {
            while(!a.empty() && nums[i%size] >= a.top())
            {
                a.pop();
            }
            res[i%size] = a.empty()? -1:a.top();
            a.push(nums[i%size]);
        }
        return res;
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值