题目描述
给每天温度,求每天还要等几天才能遇到更高温(没有就填 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)
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 个
套路模板
记住骨架:栈存下标、新元素打破单调性就弹栈结算、再入栈。改比较方向(> 换 <)就从「下一个更大」变「下一个更小」。
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 连续弹出(一个高温可能一次结算好几天)
以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握。