C++刷题笔记(44)——单调栈、leetcode739、496、503

判别是否需要使用单调栈

如果需要找到左边或者右边第一个比当前位置的数大或者小,则可以考虑使用单调栈

单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个元素比当前的元素,优点是只需要遍历一次

题目1:739.每日温度

在这里插入图片描述
维护一个存储下标的单调栈,从栈顶到栈底对应的温度呈递增顺序

从前往后遍历温度数组temperatures[i],
若栈为空,则将i入栈;

若栈不为空,则将栈顶元素对应的温度与当前温度对比,
如果当前温度大于栈顶元素对应的温度,那么将栈顶下标对应的等待天数赋值为当前温度下标减栈顶下标,将栈顶元素移除,再将当前温度下标入栈;
如果当前温度小于等于栈顶元素对应温度,则将当前温度下标入栈。
在这里插入图片描述

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        stack<int> st;
        vector<int> result(temperatures.size(), 0);
        st.push(0);  //此时栈为空,下标0直接入栈
        for (int i = 1; i < temperatures.size(); i++) {
            if (temperatures[i] < temperatures[st.top()]) st.push(i);              //当前温度 小于 栈顶元素对应的温度  直接入栈
            else if (temperatures[i] == temperatures[st.top()]) st.push(i);        //当前温度 等于 栈顶元素对应的文组  直接入栈
            else {                                                                 //栈不为空 或 当前温度大于栈顶元素对应的温度
                while (!st.empty() && temperatures[i] > temperatures[st.top()]) {  
                    result[st.top()] = i - st.top();
                    st.pop();
                }
                st.push(i);
            }
        }
        return result;
    }
};

代码优化后:

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        stack<int> st;
        vector<int> result(temperatures.size(), 0);
        for (int i = 0; i < temperatures.size(); i++) {
            while (!st.empty() && temperatures[i] > temperatures[st.top()]) {  
                result[st.top()] = i - st.top();
                st.pop();
            }
            st.push(i);
        }
        return result;
    }
};

题目2:496.下一个更大元素Ⅰ

在这里插入图片描述
和739相比增加了些难度,但解题思路还是差不多的

同样维护一个单调栈,从栈顶到栈底的元素是单调递增的

从前往后遍历nums2[i],
若栈为空,则将i入栈;

若栈不为空,则将遍历到的元素nums2[i]与栈顶元素nums2[st.top()]对比:
如果当前遍历到的元素 小于 栈顶元素,则满足栈递增(从栈顶到栈底),直接入栈;
如果当前遍历到的元素 等于 栈顶元素,因为求的是右边第一个比当前元素大的元素,也直接入栈;
如果当前遍历到的元素 大于 栈顶元素,此时若入栈则不满足栈递增,遍历到的元素就是右边第一个当前元素(栈顶元素)大的元素,再判断栈顶元素是否在nums1中出现过,如果出现过,记录当前遍历到的元素。然后将栈顶元素弹出,遍历到的元素入栈。

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        stack<int> st;
        vector<int> result(nums1.size(), -1);    //如果不存在则对应位置输出-1,因此全部初始化为-1
        if (nums1.size() == 0) return result;
        unordered_map<int, int> umap;   //key:nums1中的元素,value:下标
        for (int i = 0; i < nums1.size(); i++) {
            umap[nums1[i]] = i;
        }
        st.push(0);
        for (int i = 1; i < nums2.size(); i++) {
            if (nums2[i] < nums2[st.top()]) st.push(i);       //当前遍历到的元素 小于 栈顶元素
            else if (nums2[i] == nums2[st.top()]) st.push(i); //当前遍历到的元素 等于 栈顶元素
            else {                                            //当前遍历到的元素 大于 栈顶元素
                while (!st.empty() && nums2[i] > nums2[st.top()]) {
                    if (umap.count(nums2[st.top()]) > 0) {    //查找map李是否存在这个元素,count(key):在容器中查找以 key 键的键值对的个数
                        int index = umap[nums2[st.top()]];    //根据map找到num2[st.top()]在nums1中的下标
                        result[index] = nums2[i];             //根据nums1元素的下标来更新result数组
                    }
                    st.pop();
                }
                st.push(i);
            }
        }
        return result;
    }
};

也可以像上一题那样简化:

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        stack<int> st;
        vector<int> result(nums1.size(), -1);
        if (nums1.size() == 0) return result;

        unordered_map<int, int> umap; // key:下标元素,value:下标
        for (int i = 0; i < nums1.size(); i++) {
            umap[nums1[i]] = i;
        }
        st.push(0);
        for (int i = 1; i < nums2.size(); i++) {
            while (!st.empty() && nums2[i] > nums2[st.top()]) {
                if (umap.count(nums2[st.top()]) > 0) { // 看map里是否存在这个元素
                    int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()] 在 nums1中的下标
                    result[index] = nums2[i];
                }
                st.pop();
            }
            st.push(i);
        }
        return result;
    }
};

题目3:503.下一个更大元素Ⅱ

在这里插入图片描述

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        vector<int> result(nums.size(), -1);
        if (nums.size() == 0) return result;
        stack<int> st;
        for (int i = 0; i < nums.size() * 2; i++) {
            // 模拟遍历两边nums,注意一下都是用i % nums.size()来操作
            while (!st.empty() && nums[i % nums.size()] > nums[st.top()]) {
                result[st.top()] = nums[i % nums.size()];
                st.pop();
            }
            st.push(i % nums.size());
        }
        return result;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值