LeetCode | C++ 单调栈——单调栈理论、739. 每日温度、496.下一个更大元素 I

52 篇文章 0 订阅
文章详细介绍了单调栈在解决数组中寻找特定元素相邻更大或更小元素问题时的应用,如739.每日温度和496.下一个更大元素I。单调栈的核心是利用栈来存储元素的下标,保证栈内的元素单调递增或递减,从而在遍历过程中高效地找到目标元素。同时,文章提到了结合哈希表来加速查找过程的策略。
摘要由CSDN通过智能技术生成

单调栈

1、什么时候会用到单调栈?

通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。时间复杂度为O(n)。

单调栈的作用就是用来存放之前遍历过的元素

2、单调栈的原理是什么?

单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素(不然就不知道之前都遍历过哪些元素,以至于遍历一个元素找不到是不是之前遍历过一个更小的),优点是整个数组只需要遍历一次。

3、在使用单调栈需要明确以下几点:

  • 单调栈里存放的元素是什么?
    单调栈里只需要存放元素的下标 i 就可以了,如果需要使用对应的元素,直接T[i] 就可以获取。
  • 单调栈里元素是递增呢? 还是递减呢?
    注:以下内容中,顺序的描述为 从栈头到栈底的顺序
    如果求一个元素右边或者左边第一个更大元素,单调栈就是递增的,如果求一个元素右边或者第一个更小元素,单调栈就是递减的。

4、使用单调栈主要有三个判断条件

  • 当前遍历的元素 T[i] 小于 栈顶元素 T[st.top()] 的情况
  • 当前遍历的元素 T[i] 等于 栈顶元素 T[st.top()] 的情况
  • 当前遍历的元素 T[i] 大于 栈顶元素 T[st.top()] 的情况

739. 每日温度

739题目链接
为什么栈里面的元素是保证单调递增的,因为只有这样,当遍历元素大于栈顶元素时,才能计算栈顶元素在数组里它右面第一个比栈顶元素大的,其实就是我们正在遍历的这个元素。

当遍历元素 小于 栈顶元素时: 入栈

当遍历元素 等于 栈顶元素时: 入栈

当遍历元素 大于 栈顶元素时: 需要对栈顶元素( 下标 )的 result 结果进行赋值,然后将栈顶元素弹栈,继续比较,直到不大于为止。

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        stack<int> st;
        vector<int> result(temperatures.size(), 0);
        st.push(0);
        for (int i = 1; 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;
    }
};

496.下一个更大元素 I

496题目链接
单调栈 + 哈希表

单调栈:对于nums2 利用递增 单调栈 找到每个元素 右边第一个更大元素

哈希表:利用map 去做映射(key : 下标元素, value : 下标),根据map 快速找到下标,同时判断 nums2[i] 是否在 nums1 中出现过, 对于出现过的,找到对应result 里 下标 进行赋值。

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        vector<int> result(nums1.size(), -1);
        unordered_map<int, int> umap; // key:下标元素,value:下标
        for (int i = 0; i < nums1.size(); i++) {
            umap[nums1[i]] = i;
        }
        stack<int> st;
        for (int i = 0; i < nums2.size(); i++) {
            while (!st.empty() && nums2[i] > nums2[st.top()]) {
                if (umap.find(nums2[st.top()]) != umap.end()) {
                    int index = umap[nums2[st.top()]];
                    result[index] = nums2[i];  
                }  
                st.pop(); 
            }
            st.push(i);
        }
        return result;
    }
};

参考

代码随想录

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值