算法困惑问答 · LC 739 每日温度
每日温度的单调栈里,为什么存下标而不是温度?
直接答案
因为答案要的是「还要等几天」,它等于两个位置的差 i − j——这个减法只有下标能做。栈里存温度的话,结算时你知道「等到了更热的一天」,却说不出等了几天。反过来,存下标毫无损失:想要温度,拿下标回数组里取就是了。单调栈类题目的通用原则:栈里默认存下标,值可以随时由下标还原,下标却无法由值还原。
弹栈的瞬间就是结算的瞬间
栈里压着的是「还没等到更热天气」的日子的下标,从底到顶温度递减。新的一天 i 到来,只要 T[i] 比栈顶下标 j 对应的温度高,就把 j 弹出结算:answer[j] = i − j,正是 j 这天等待的天数。弹完若还比新栈顶热,继续弹、继续填;弹不动了(或栈空了),把 i 自己压进去,等未来更热的一天来叫醒它。
这套机制为什么是 O(n):每个下标恰好入栈一次,至多出栈一次,所有 while 弹栈的总次数不超过 n。别被「for 里套 while」的样子吓到,摊还下来就是线性。
两个高频翻车点
弹栈条件必须是严格大于:T[i] > T[栈顶]。温度相等不算「更热」,相等的那天还得继续在栈里等。写成 ≥ 会把「等到了平局」误判成「等到了答案」。
扫完之后还留在栈里的下标,代表到最后也没等到更热的天,answer 保持初始值 0 即可——所以答案数组初始化为全 0,收尾不需要任何额外处理。
代码关键行(Python)
def dailyTemperatures(T):
ans, stack = [0] * len(T), [] # 栈里存下标
for i, t in enumerate(T):
while stack and t > T[stack[-1]]: # 严格更热才弹
j = stack.pop()
ans[j] = i - j # 下标相减 = 等的天数
stack.append(i)
return ans`ans[j] = i - j` 这行就是「为什么存下标」的答案:等待天数是位置差。栈里若存的是温度,这行减法根本写不出来。
常见追问
如果题目改问「下一个更高温的温度值」呢?
同一套栈,弹出 j 时记录 T[i](当前温度)而不是 i − j 即可,这就是「下一个更大元素」(LC496)的模板。存下标的写法两种问法都能答,再次说明存下标信息无损。
什么时候栈里可以只存值?
只有当答案完全不涉及位置(不算距离、不算宽度、不回填答案数组)时才行,实际很少见。养成「默认存下标」的习惯,几乎不会错。
把这道题彻底吃透
LC 739「每日温度」有逐步交互动画和完整图文题解,配着本页的结论看,一遍就通。