当前:LC739 · 每日温度 · 首次出现于 Day 43 · 路径:顶栏「56天打卡」→ 点击 LC 题号 → 逐题动画

LC739 · Daily Temperatures · 单调栈

每日温度:递减栈里等一个更热的天

答案是距离不是温度。栈里放下标,温度自底到顶递减;更热的一天到来,把还在等的天一次性结清。

维护温度递减的下标栈。从左扫到第 i 天:只要今天比栈顶那天热,就弹出栈顶 j,answer[j] = i−j。弹完把 i 入栈。扫完仍留在栈里的天右边再没有更热,答案保持 0。时间 O(n),空间 O(n)。

时间 O(n)空间 O(n)结论先行 · 全文约 6 节
导读

这是 LeetCode 739. Daily Temperatures。给你每天的温度,返回数组 answer,answer[i] 表示还要等几天才会遇到更高的温度;右边再也没有更高就填 0。

主例 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],答案 [1, 1, 4, 2, 1, 1, 0, 0]。73 第二天就 74;75 要等到四天后的 76;最后的 76 和 73 右边没有更高,两个 0。

对每个 i 往右线性找第一个更大,平方级能做对。缺的是:许多天在等同一场升温,不必各自重扫。本文把「还没等到更热」的下标压进递减栈,更热的一天到了就批量结算距离。

读题:问的是距离

把句子翻成下标:answer[i] = j−i,其中 j 是 i 右边第一个 temps[j] > temps[i] 的位置;没有这样的 j 就 0。主例里 75 的 j 是 76 所在的下标 6,6−2=4;71 的 j 是 72 所在的下标 5,5−3=2。

这和「下一个更大元素」是同一件事,只是账本不同:LC496 记那个更大的值,这里记下标差。栈里因此必须放下标,温度用 temps[栈顶] 去读。没有更热填 0,正好当答案数组的初值,不必在收尾时再扫一遍栈。

模型下一个更大元素换了问法:值换成距离。递减栈的弹出条件仍是「当前比栈顶热」,结算的是 i 减栈顶下标。

递减栈存下标,遇到更热批量结算

栈里是还没找到更热天气的下标,对应温度自底到顶递减。栈顶是这些「等待者」里最近、也最容易被今天解约的一天:今天只要比它热,它的答案就是今天。弹完之后新的栈顶更早、也更热,再问一次今天够不够。

第 i 天到来:当栈非空且 temps[i] > temps[栈顶],弹出 j,res[j]=i−j;重复直到栈空或栈顶那天仍然 ≥ 今天。然后把 i 入栈。今天自己也开始等后面更热的天。

用手走主例,对应演示。i=0,73 入栈。i=1,74>73,弹出 0,res[0]=1,74 入栈。i=2,75>74,弹出 1,res[1]=1,75 入栈。栈里只剩下标 2。i=3、4,71 和 69 都比 75 冷,依次入栈,谁也还不了 75。

i=5,72>69,弹出 4,res[4]=1;72 仍小于 75,71 若还在栈里也会被 72 弹出,res[3]=2。i=6,76 比栈里剩下的 72、71、75 都热,依次结算:res[5]=1、res[3]=2、res[2]=4,演示写「76 弹出 72、69、71、75」。i=7,73<76,入栈。扫完栈里剩 76 和 73,答案保持 0。整份答案 [1,1,4,2,1,1,0,0]。

76 出现,批量结算 69、72 下标
7374757169727673
递减栈(存下标)
0
answer
00000000
73 入栈

Go:递减栈(存下标)

solution.goGo
func dailyTemperatures(temps []int) []int {
n := len(temps)
res := make([]int, n)
stack := []int{}
for i, t := range temps {
for len(stack) > 0 && temps[stack[len(stack)-1]] < t {
j := stack[len(stack)-1]
stack = stack[:len(stack)-1]
res[j] = i - j
}
stack = append(stack, i)
}
return res
}

1res 默认 0。扫完仍在栈里的下标,包括主例最后的 76 和 73,保持 0。

2栈里是下标。比较用 temps[栈顶] < 今天,严格更热才结算;相等继续等。

3弹出的 j 把答案写成 i−j。主例 75 被 76 弹出时 6−2=4。

4今天入栈。每个下标入栈一次、出栈至多一次,总时间线性。

总结

递减栈存下标,更热的天批量结距离。主例 76 一次还清 75 的 4 天。

  • 问距离就必须压下标,不能只压温度。
  • 栈里温度递减,栈顶是最近那个还在等的人,先被今天解约。
  • 496 / 503 / 739 同一只栈,分别记值、记环上的值、记距离。
同族题目
LC496下一个更大元素 ILC503下一个更大元素 IILC42接雨水(同款递减栈)