每日温度
Daily Temperatures
对每一天,求还要等几天才会出现更高温度;如果之后都不会升温,就填 0。
在力扣中练习题目描述
给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 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]
提示:
1 <= temperatures.length <= 10530 <= temperatures[i] <= 100
解题思路
单调栈 · 存下标
把还没等到答案的天攒在栈里,一升温就集中结算
为每一天向后扫描更暖天气,会重复检查很多相同区间。改成维护“还没等到答案的日子”,新温度到来时只结算比它低的栈顶。
自拟主例 [68,72,72,65,70,74,71],答案是 [1,4,3,1,1,0,0]。栈里保存下标,温度从栈底到栈顶不递增;两个 72 相等,都必须继续等待。
第 1 天 72° 入栈,等待后续更高温度。
- 72第 1 天← top
74 到来时,70 和两个 72 会依次出栈。每弹出下标 j,等待天数就是当前下标 i 减 j,而不是温度差。
第 4 天 70° 入栈,等待后续更高温度。
- 72第 1 天
- 72第 2 天
- 70第 4 天← top
每个下标只入栈一次、出栈一次。扫描结束后仍留在栈里的日子等不到更暖天气,答案保留初始的 0,不需要额外清栈填值。
易错点
- 把 while 写成 if:一次升温可能同时解决栈里好几天,比如 [75,71,69,72] 里的 72 要连弹两次。
- 栈里存温度而不是下标,最后算不出「几天后」。
- 比较写成 >=:温度相等不该算「更高」,会被提前弹出。
暴力 · 往后找
对每一天向后扫,找到第一个更暖的为止
结果正确,但最坏 O(n²),大输入可能超时;仅用于理解单调栈消除了哪些重复扫描。
最直白的写法:对每个 i,从 i + 1 开始往后找第一个 temperatures[j] > temperatures[i],找到就填 j - i 并 break;扫到末尾都没找到,就保持 0。
它的正确性没有任何疑问,问题全在效率:数组严格递减时(比如 [100, 99, 98, ...]),每一天都要扫到末尾,总比较次数是 n²/2 级别。题目给到 10⁵,这个量级会超时。
不过它是理解单调栈的好起点:单调栈做的正是把这些「往后找」的扫描结果缓存下来——某一天如果已经被后来的暖天结算过,就再也不用为它重复扫描了。
写完暴力再回头看单调栈,会发现两者在枚举的对象上完全不同:暴力枚举「哪一天更暖」,单调栈枚举「哪一天还没答案」。
- 1answer 初始化为 0。
- 2外层 i 枚举每一天。
- 3内层 j 从 i + 1 往后找第一个更暖的天。
- 4找到就写 answer[i] = j - i 并 break。
易错点
- 找到后忘记 break,后面的暖天会覆盖掉正确答案。
- 内层循环写成 j <= n,越界访问 temperatures[n]。
代码与演示
主解法配有图解;对照解法用于比较思路、复杂度或实现方式。
temperatures = [68, 72, 72, 65, 70, 74, 71]答案先填 0;栈保存等待中的下标,相等温度不会让栈顶出栈。
查看 C++ 代码
延伸阅读
- 单调栈模板就三行:栈非空且当前元素破坏单调性时,弹栈并结算答案;然后压栈。下一个更大元素(496/503)、接雨水(42)、柱状图中最大的矩形(84)都是它的变形。
- 本题是「下一个更大元素」的距离版本:把 answer[j] = i - j 换成 answer[j] = temperatures[i],就变成了存值的版本。
- 从右往左扫也能做,配合已经算好的 answer 往前跳,思路更接近记忆化;但单调栈的写法更统一,也更适合推广。