主题
复盘 · LC 739 每日温度
题目
- 题号:LeetCode 739
- 名称:每日温度(Daily Temperatures)
- 难度:Medium
- 链接:leetcode.cn/problems/daily-temperatures
- 今日代码:
739-每日温度/index.js
题意
给定 temperatures[i] 表示第 i 天的温度,返回数组 answer,其中 answer[i] 是第 i 天之后第一次出现更高温度还要等几天;若不存在更高温度则为 0。
- 长度可达 10⁵,需要 O(n) 级解法。
- 边界:全递减(全 0)、全相等(全 0)、最后一天(必为 0)。
涉及算法
| 标签 | 一句话 |
|---|---|
| 单调栈 | 维护「温度单调递减」的下标栈,遇更高温时弹栈结算等待天数 |
| 栈 | LIFO 存「还没找到答案的天」 |
教程对照:10 · 栈 精讲 739 段——从左扫、栈存下标、弹栈写 ans[j] = i - j。
评价我的解法
你的思路:从右往左扫,单调栈里压 { value, index },右边第一个更暖的天就是栈顶。逻辑是对的,属于「反向单调栈」变体。
我的代码(摘自 739-每日温度/index.js,不含测例):
javascript
var dailyTemperatures = function (temperatures) {
const resultArr = Array.from({
length: temperatures.length,
}).fill(0);
const stack = [];
let i = temperatures.length - 1;
for (; i >= 0; i--) {
const item = temperatures[i];
if (stack.length === 0) {
stack.push({
value: item,
index: i,
});
continue;
}
let topObj = stack[stack.length - 1];
if (item < topObj.value) {
resultArr[i] = topObj.index - i;
stack.push({
value: item,
index: i,
});
} else {
while (stack.length) {
topObj = stack[stack.length - 1];
if (item < topObj.value) {
break;
} else {
stack.pop();
}
}
if (stack.length > 0) {
resultArr[i] = topObj.index - i;
}
stack.push({
value: item,
index: i,
});
}
}
return resultArr;
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
对在哪
- 单调栈骨架到位:更冷的天弹掉、更暖的留在栈里当「下一个更大」。
- 用
topObj.index - i算天数,下标语义正确。 - 本地测例
[73,74,75,71,69,72,76,73]输出正确。
糙在哪
- 栈里存对象
{ value, index }:值可从temperatures[index]取,多存一份且多分配对象;LeetCode 上用时 59ms、击败约 5.65%,偏慢。 - 反向扫 + 分支重复:
item < topObj时 push 的逻辑写了两遍(if分支和else里while之后),可合并成「先 while 弹栈,再若栈非空写答案,最后 push」。 - 与教程模板方向相反:默写和口述更顺的是从左到右、栈只存下标;反向版能过,但面试白板不如正向好讲。
复杂度:每个下标最多入栈、出栈一次 → 时间 O(n);空间 O(n)(对象栈常数更大)。
最佳题解
正向单调递减栈,只存下标(与教程一致):
javascript
/**
* @param {number[]} temperatures
* @return {number[]}
*/
var dailyTemperatures = function (temperatures) {
const n = temperatures.length;
const ans = new Array(n).fill(0);
const stack = []; // 下标,对应温度单调递减
for (let i = 0; i < n; i++) {
while (stack.length && temperatures[stack.at(-1)] < temperatures[i]) {
const j = stack.pop();
ans[j] = i - j;
}
stack.push(i);
}
return ans;
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 时间 O(n),空间 O(n)。
- 为何更优:一遍正向、无多余对象、与「下一个更大元素」全家桶同一模板;口述就是「更热就弹栈结算,再把今天压进去」。
关联题目
| 题 | 为何相关 |
|---|---|
| 496. 下一个更大元素 I | 同一单调栈,答案映射到元素 |
| 503. 下一个更大元素 II | 循环数组版单调栈 |
| 84. 柱状图中最大的矩形 | 单调栈进阶:弹栈算宽度 |
一句话带走
每日温度:从左扫,栈存下标且温度递减;当前更热就 while 弹栈,被弹的下标答案 = 当前下标 − 被弹下标。
