每日温度

131 阅读2分钟

这是我参与11月更文挑战的第29天,活动详情查看:2021最后一次更文挑战

739. 每日温度

问题描述

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

示例:

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

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

分析问题

既然是求每一天需要等几天才会有更高的温度,那么最直观的想法就是针对气温列表 temperatures 中的每个温度值,向后依次进行搜索,找到第一个比当前温度更高的值的位置索引,然后减去当前温度所在的位置索引,就是要求的结果。

下面我们来看一下代码的实现。

class Solution(object):
    def dailyTemperatures(self,temperatures):
        #求出温度列表的长度
        n = len(temperatures)
        result=[0]*n
        #遍历每一个温度值
        for i in range(n):
            if temperatures[i]<100:
                #想后搜索第一个大于当前温度值的元素
                for j in range(i+1,n):
                    if temperatures[j] > temperatures[i]:
                        result[i]=j-i
                        break

        return result

该算法的时间复杂度是O(n^2),空间复杂度是O(n)。

显然该算法的时间复杂度太高,那我们有什么优化的方法吗。

优化

我们这里可以使用单调栈来优化,即维护一个温度值下标的单调栈,使得从栈顶到栈底的的元素对应的温度值依次递减。具体来说,我们正向遍历温度列表 temperatures。对于温度列表中的每个元素 temperatures[i]。如果栈为空,则直接将 i 进栈;如果栈不为空,则比较栈顶元素 prev 对应的温度值 temperatures[prev] 和 当前温度 temperatures[i]。

  • 如果 temperatures[prev] < temperatures[i],则将栈顶元素 prev 移除,此时 prev 对应的等待天数为 i - prev。重复上述操作直到栈为空或者栈顶元素对应的温度大于等于当前温度,然后将 i 进栈。

  • 如果 temperatures[prev] > temperatures[i],则直接将元素 i 入栈。

下面我们来思考一个问题,为什么可以在出栈的时候更新等待天数 result[prev] 呢?因为即将进栈的元素 i 对应的温度值 temperatures[i] 一定是 temperatures[prev] 右边第一个比它大的元素。

下面我们来看一个具体的例子,假设温度列表 temperatures = [73,74,75,71,69,72,76,73] 。

初始时,单调栈 stack 为空;等待天数 result 为 [0,0,0,0,0,0,0,0]。

image-20211129124347950

image-20211129124411253

image-20211129124507019

image-20211129124531093

image-20211129124608472

image-20211129124634335

image-20211129124752957

image-20211129124817867

image-20211129124851144

下面我们来看一下代码的实现。

n = len(temperatures)
        #初始化一个空的栈
        stack = []
        result = [0] * n
        for i in range(n):
            temperature = temperatures[i]
            #如果 temperatures[i] 大于栈顶元素对应的温度值,则栈顶元素出栈。
            while stack and temperature > temperatures[stack[-1]]:
                prev = stack.pop()
                result[prev] = i - prev
            stack.append(i)
        return result

该算法的时间复杂度是O(n),空间复杂度也是O(n)。