每日温度 单调栈

739. 每日温度

请根据每日 气温 列表 temperatures 请计算在每一天需要等几天才会有更高的温度。如果气温在这之后都不会升高,请在该位置用 0 来代替。

示例 1:

输入: temperatures = [73,74,75,71,69,72,76,73]

输出: [1,1,4,2,1,1,0,0]

示例 2:

输入: temperatures = [30,40,50,60]

输出: [1,1,1,0]

示例 3:

输入: temperatures = [30,60,90]

输出: [1,1,0]

(下面都是分析,要直接看代码请直接拉到最底下!!)

思路:

  直接说思路吧,我们需要用单调栈去做这道题。这道题要求的是求出一个数组当中,每一个数的下一个较大的值在哪个位置。不管是下一个较大值还是下一个较小值,不管是求绝对位置(具体下标)还是相对位置(离它的距离),这都是一个单调栈就可以解决的问题。

  以后我们在有类似的需求:求下一个较大值、下一个较小值时,就直接用单调栈即可。

  什么是单调栈?就是一个只允许我们存放按顺序上升或下降的数的栈。比如有一个递减单调栈,每次我们添加元素,都要判断栈顶元素是不是比当前元素大,满足条件我们才能添加;如果不满足条件,就把栈顶元素弹出pop(),再比较新的栈顶元素和要添加元素的大小,直到满足条件我们才能添加新元素。若一直不满足条件,我们甚至不惜把栈全置空再添加元素,以便绝对遵守递减的性质。

  就算直到单调栈的性质,那它这一特性又和我们的题目有啥关系呢——单调栈是我们得到题目结果过程当中的的一个辅助数据结构。利用单调栈的性质,再按照特定的顺序遍历给定数组,在操作单调栈过程中将中间结果添加进结果数组就可以得到结果。

  具体怎么导入,怎么操作,可以去看,但是看了马上就会忘记。四个月前我把“为啥这样就能利用单调栈求出结果”的代码原理和逻辑在脑海里过得明明白白,但现在我再整理这个的时候,又感觉十分陌生和抽象了。

  人的大脑是真的无法永久记忆的,曾经的我误以为LeetCode题目刷多了可以变得聪明、变得睿智,但实际上,刷题除了保持短期内对题目的熟悉和对套路的熟练之外,没有别的长期作用。所以并不强求去理解原理,我们唯一要记住的就是它的应用场景——求下一个较大、较小值;以及它的代码实现框架、套路就好了。因为我们的重点就是把题做出来,把题做出来只需要两步:知道要用什么方法,知道这个方法怎么用。

单调栈模板:

def 模板函数(nums):

    lenth = len(nums)

    stack=[]#定义单调栈,存储的是下标

    res = [0]*lenth#定义存储结果的列表

    for i in range(lenth-1,-1,-1):

        while(stack and nums[stack[-1]]<=nums[i]):#判断需要弹出条件

            stack.pop()

        #pop完后 栈顶元素可以给res了

        res[i]=stack[-1] if stack else 0#如果stack没有值,给缺省值0

        stack.append(i)#添加入单调栈

    return res
  下面这一段话不需要完全理解,能看就看,看不懂也不要纠结,无所谓的,我写这段的目的就是辅助我们理解并记住模板——因为只要记住一半的逻辑就很有助于我们记忆实现方式:
  (这段话,随缘看)简单描述一下这个模板的逻辑:我们从后往前地遍历给定数组,准备把当前值对应的下标加入单调栈。之前已经说过了,单调栈添加元素,要满足它对应的升上/下降性质,所以我们要拿当前值和栈顶元素(是个下标)在数组中对应的值进行比较,从而先进行栈的pop()操作。弹出元素之后,不要着急添加这个新下标,先在中间加入我们存放结果的语句:将此时的栈顶元素赋给结果列表,若此时栈顶元素为空,则赋我们给定的缺省值0(也可以是其他任何值)。最后添加我们的新下标。
 

  好了,不管有没有看懂上面这段话,我们一定要做的就是记住这个模板的实现方式和使用方式

先说一下这个模板函数的作用:

传入数组nums,得到与nums对应的下一个较大值下标

比如对于[3,4,1,2,1,4],可以得到[1, 0, 3, 5, 5, 0]。其中0就是缺省值。

上面这句话的两处红色部分,是可以灵活修改的。

一、如果我们要得到下一个较小值下标,只需 while(stack and nums[stack[-1]]<=nums[i]):

        改成

        while(stack and nums[stack[-1]]>=nums[i]):

        就可以得到下一个较小值下标

        比如对于[3,4,1,2,1,4],可以得到[2, 2, 0, 4, 0, 0]

二、如果我们要得到下一个较大值距离。(这个距离是指与当前位置的距离,也正是“每日温度”这一题的要求)只需将 res[i]=stack[-1] if stack else 0

        改成

        res[i]=stack[-1]-i if stack else 0

        比如对于[3,4,1,2,1,4],可以得到[1, 0, 1, 2, 1, 0]

三、若要得到下一个较小值距离

        则两处同时改,就好了:

        首先  while(stack and nums[stack[-1]]<=nums[i]):

        改成

        while(stack and nums[stack[-1]]>=nums[i]):

        再将 res[i]=stack[-1] if stack else 0

        改成

        res[i]=stack[-1]-i if stack else 0.

  回到这一题,题目要求的就是下一个较大值距离。其实就是第二种改法直接套模板:

代码:

class Solution(object):
    def dailyTemperatures(self, T):

        stack=[]

        lenth = len(T)

        res = [0]*lenth

        for i in range(lenth-1,-1,-1):

            while stack and T[stack[-1]]<=T[i]:#第一处修改,写成<=

                stack.pop()

            res[i] = stack[-1]-i if stack else 0#第二处修改,加上-i

            stack.append(i)

        return res
 

posted @   JunanP  阅读(9)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示