739. 每日温度

Description

image-20210828114330017

Simulation

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

第1天第2天第3天第4天第5天第6天第7天第8天
温度7374757169727673
下一个更高的温度第2天第3天第7天第6天第6天第7天
天数差11421100

首先想到的当然是暴力解法,两层 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. 在模板的基础上进行删改,计算题目要求。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mancuoj

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值