一道Medium,两道Hard带你刷爆力扣单调栈(一)

简介: 一道Medium,两道Hard带你刷爆力扣单调栈(一)

Preface


继上篇【面试高频】详解单调栈,今天我们来讲述一下如何用我给出的单调栈模板刷题。

所谓单调栈其实就是栈内元素具有单调性, 常用于解决下一个更大元素 这种问题。

我们会讲一下其中最具代表性的三道题,其中一道Medium,两道Hard,保证你看完一定有所收获:



// 单调栈模板,如果不懂可以看我的上篇文章
 for (遍历这个数组) {
     while (栈不为空 && 栈顶元素与当前数组元素比较) {
         出栈;
     }
     入栈; 
 }
复制代码


739. 每日温度



Description



image.png

Simulation


思路:我们先列一个表格分析一下示例数据是怎么来的


第1天 第2天 第3天 第4天 第5天 第6天 第7天 第8天
温度 73 74 75 71 69 72 76 73
下一个更高的温度 第2天 第3天 第7天 第6天 第6天 第7天
天数差 1 1 4 2 1 1 0 0

首先想到的当然是暴力解法,两层 for 循环挨个遍历一遍,计算天数差即可,时间复杂度O(n^2)。


get到暴力解法也很重要,毕竟不是什么时候都能想到最优解,而且我们还可以基于暴力解法进行下一步优化。


题目中要求计算下一个更高的温度的天数差,其实就是要找到自己右边第一个比自己大的元素, 然后计算下标之差


很明显要用到一个单调减(栈头元素最小)的栈,通过O(n)的时间复杂度(即遍历一遍)就能找到每个元素的右边第一个比它大的元素,本质就是空间换时间。


  1. 为什么是单调减?
    答:因为只有递减的时候,我们才能得到天数差,如74放入栈时,73即可出栈,第一天的天数差就得到了。
  2. 怎么计算天数差?
    答:单调栈内只存放元素的下标即可,需要数值比较时直接使用 t[i] 即可。
  3. 模板怎么用?⏬


既然已经分析出要用单调栈,我们可以直接把三板斧(模板)使出来:


// 模板
 stack<int> stk;
 for (int i = 0; i < t.size(); i++) {                // 遍历温度数组t
     while (!stk.empty() && t[i] > t[stk.top()]) {   // 出栈条件,保持单调减
         stk.pop();
     }
     stk.push(i);                                    // 入栈,放入下标
 }
复制代码


在脑中模拟一下出入栈的过程:


  • 栈为空,73的下标0入栈,栈内元素 0
  • 74 > 73,73出栈74入栈,天数差为1,栈内元素 1
  • 75 > 74,74出栈75入栈,天数差为1,栈内元素 2


从第二步就可以看出来,我们需要在栈内元素出栈前通过下标计算天数差,增加一行即可:


while (!stk.empty() && t[i] > t[stk.top()]) {   // 出栈条件,保持单调减
         res[stk.top()] = i - stk.top();    // 添加计算
         stk.pop();
     }
复制代码


Solution


完整代码如下,可以尝试一下,原题链接


// hrh 8/28 
 class Solution {
 public:
     vector<int> dailyTemperatures(vector<int>& t) {
         vector<int> res(t.size());
         stack<int> stk;     
         for (int i = 0; i < t.size(); i++) {                // 遍历
             while (!stk.empty() && t[i] > t[stk.top()]) {   // 出栈条件
                 res[stk.top()] = i - stk.top();             // 计算天数差值
                 stk.pop();                                  // 保持单调减
             }
             stk.push(i);                                    // 入栈
         }
         return res;
     }
 };
复制代码


Conclusion


总结一下单调栈的分析思路:


  1. 一般来说,题目中要求找到一个元素左边(右边)第一个比自己大(小)的元素,我们应该首先想到单调栈。它的应用范围可以说是很窄,但缺点也是优点,题目类型很好辨认。
  2. 分析时应该首先分析单调性,判断单调减还是单调增,直接写出模板。
  3. 在模板的基础上进行删改,计算题目要求。
目录
相关文章
|
5月前
|
存储 算法 测试技术
力扣经典150题第五十四题:最小栈
力扣经典150题第五十四题:最小栈
45 0
|
6月前
|
存储 算法 索引
力扣每日一题 6/24 模拟 数组 单调栈
力扣每日一题 6/24 模拟 数组 单调栈
42 0
|
2月前
【LeetCode 24】225.用队列实现栈
【LeetCode 24】225.用队列实现栈
16 0
|
2月前
|
算法
【LeetCode 23】232.用栈实现队列
【LeetCode 23】232.用栈实现队列
26 0
|
4月前
|
Python
【Leetcode刷题Python】946. 验证栈序列
LeetCode题目“946. 验证栈序列”的Python解决方案,通过模拟栈的压入和弹出操作来验证给定的两个序列是否能通过合法的栈操作得到。
36 6
|
4月前
|
Python
【Leetcode刷题Python】剑指 Offer 30. 包含min函数的栈
本文提供了实现一个包含min函数的栈的Python代码,确保min、push和pop操作的时间复杂度为O(1)。
35 4
|
4月前
|
Python
【Leetcode刷题Python】剑指 Offer 09. 用两个栈实现队列
使用两个栈实现队列的Python解决方案,包括初始化两个栈、实现在队列尾部添加整数的appendTail方法和在队列头部删除整数的deleteHead方法,以及相应的示例操作。
42 2
|
4月前
|
Python
【Leetcode刷题Python】232. 用栈实现队列
如何使用Python语言通过两个栈来实现队列的所有基本操作,包括入队(push)、出队(pop)、查看队首元素(peek)和判断队列是否为空(empty),并提供了相应的代码实现。
25 0
|
6月前
|
存储 算法 Python
二刷力扣--栈和队列
二刷力扣--栈和队列
|
6月前
|
存储 算法 数据可视化
力扣155题最全解法:如何实现支持常数时间获取最小值的最小栈(附详细图解和复杂度分析)
力扣155题最全解法:如何实现支持常数时间获取最小值的最小栈(附详细图解和复杂度分析)