图解题库 / 单调栈

739. 每日温度

中等 含交互动画

学完这道你应该能: 说清它为什么用「单调栈」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

题目描述

给每天温度,求每天还要等几天才能遇到更高温(没有就填 0)。

temps = [73, 74, 76, 72, 75]
输出 = [1, 1, 0, 1, 0]

思路解析

对每天都往后扫,最坏 n² 次。换个思路:用一个栈记住「还没等到更暖天」的下标,新的一天来了就一次性结算它们。

栈里放「在等更暖一天」的下标。新一天温度若高于栈顶那天,就说明栈顶等到了——弹出并算天数差。重复直到栈顶比它高,再把今天压栈。

i=0 · 73 入栈:第 1 天 73,栈空,直接压入下标 0。它开始「等更暖的一天」。

i=1 · 74 > 73:74 比栈顶那天(73)高!第 0 天等到了:ans[0] = 1 − 0 = 1。弹出 0,再压入今天 1。

i=2 · 76 > 74:76 又比栈顶(74)高,第 1 天等到了:ans[1] = 2 − 1 = 1。弹出 1,压入今天 2。

i=3 · 72 < 76:72 比栈顶(76)低,第 2 天还得继续等。今天也开始等,压入 3。栈里现在有两天 [2, 3]。

i=4 · 75 > 72:75 高于栈顶(72):ans[3] = 4 − 3 = 1。但 75 仍低于下面的 76,停止弹出,压入今天 4。

收尾 · 剩 [2,4]:扫描结束,栈里还剩第 2、4 天没等到更暖的,它们的答案就是 0。最终 [1,1,0,1,0]

凡是「找下一个更大/更小的元素」,都用单调栈:每日温度、下一个更大元素、柱状图最大矩形都是它。

参考代码(Python)

Python
1ans = [0] * len(temps)
2stack = []                       # 存「还在等」的下标
3for i, t in enumerate(temps):
4    while stack and t > temps[stack[-1]]:   # 今天更暖
5        j = stack.pop(); ans[j] = i - j     # 第j天等到了
6    stack.append(i)
7return ans

复杂度分析

  • 时间复杂度:O(n) —— 每个下标进出栈一次
  • 空间复杂度:O(n) —— 栈最多装 n 个

套路模板

记住骨架:栈存下标、新元素打破单调性就弹栈结算、再入栈。改比较方向(> 换 <)就从「下一个更大」变「下一个更小」。

Python
1# 「为每个元素找右边第一个更大/更小」都套
2stack = []                       # 存还没找到答案的下标
3for i, x in enumerate(arr):
4    while stack and x > arr[stack[-1]]:   # 维持递减栈
5        j = stack.pop(); ans[j] = i - j   # 结算 j
6    stack.append(i)

易错点

  • 栈里存温度值 → ✅ 存下标(要算「天数差」必须知道位置)
  • while 写成 if → ✅ 用 while 连续弹出(一个高温可能一次结算好几天)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →283. 移动零 ← 返回题库