在问 · 算法题解

739. 每日温度

题目描述

输入整数数组 temperatures,temperatures[i] 是第 i 天的气温。

返回与它等长的数组 answer。answer[i] 等于从第 i 天往后,第一次出现严格更高气温的那一天与第 i 天相差的天数。

如果第 i 天之后再也没有更高的气温,answer[i] 为 0。

示例 1
输入:temperatures = [73,74,75,71,69,72,76,73]
输出:[1,1,4,2,1,1,0,0]

解释:例如第 2 天气温 75,下一次更高的是第 6 天的 76,相隔 4 天。

示例 2
输入:temperatures = [30,40,50,60]
输出:[1,1,1,0]
示例 3
输入:temperatures = [30,60,90]
输出:[1,1,0]

数据范围

  • 1 <= temperatures.length <= 10^5
  • 30 <= temperatures[i] <= 100

解题思路:单调栈

单调递减栈结算更高温度。

为什么正确

栈内下标递增,对应温度单调不增(相等温度也保留);每个下标等待右侧第一个严格更高温度。

复杂度分析

时间 O(n),额外空间 O(n)。

易错点

注意边界条件并在回溯或弹出后恢复状态。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
 def dailyTemperatures(self,a):
  out=[0]*len(a);st=[]
  for i,x in enumerate(a):
   while st and a[st[-1]]<x:j=st.pop();out[j]=i-j
   st.append(i)
  return out

载入编辑器,自己跑一遍 →

其他解法

单调栈是“下一个更大元素”的通用模板;按温度记录依赖值域很小;从右向左跳跃省掉了栈,是单调栈思想的另一种实现。

解法 2:按温度记录最近位置 时间 O(n·m),空间 O(m)

温度只有 30 到 100 共 m = 71 种。从右往左遍历,用数组 next[t] 记录温度 t 在当前位置右边最早出现的下标。对下标 i,枚举所有比 temperatures[i] 高的温度,取 next 中最小的下标得到答案,然后更新 next[temperatures[i]] = i。

利用了温度取值范围小的条件,思路直白。值域大时不可用,比单调栈慢约 m 倍。

class Solution:
    def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
        n = len(temperatures)
        INF = n + 1
        nxt = [INF] * 101
        ans = [0] * n
        for i in range(n - 1, -1, -1):
            t = temperatures[i]
            best = INF
            for w in range(t + 1, 101):
                best = min(best, nxt[w])
            if best < INF:
                ans[i] = best - i
            nxt[t] = i
        return ans

解法 3:从右向左跳跃 时间 O(n),空间 O(1)

从右往左计算答案。对下标 i,从 j = i + 1 开始:如果 temperatures[j] 更高就找到了;否则比 j 温度低或相等的位置都不可能是答案,直接跳到 j + ans[j]。ans[j] 为 0 说明右边没有更高的,答案为 0。

复用已算出的答案做跳跃,除输出外只用 O(1) 空间。跳跃链就是从右向左的单调栈,均摊分析同样是 O(n),但不如单调栈直观。

class Solution:
    def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
        n = len(temperatures)
        ans = [0] * n
        for i in range(n - 2, -1, -1):
            j = i + 1
            while temperatures[j] <= temperatures[i]:
                if ans[j] == 0:
                    j = -1
                    break
                j += ans[j]
            if j != -1:
                ans[i] = j - i
        return ans

栈与堆 专题的其他题目

查看 栈与堆 全部题目 →