第3章|栈与队列
Unit 08 · 当前元素批量解决历史问题
当前温度不只描述今天,
还会一次解决多个等待中的过去。
普通“下一个更大元素”只需要记录更大的值;本题还要回答等待了几天,因此单调栈必须保存日期索引。某个历史日期出栈时,当前索引与它的差值就是最终答案。
题目要求
给定整数数组 temperatures,其中 temperatures[i] 表示第 i 天温度。返回数组 answer:answer[i] 表示从第 i 天起,需要等待多少天才会出现更高温度;若之后没有更高温度,则为 0。
输入、输出与复杂度目标
- 输入:每日温度数组;输出:等长等待天数数组;
- 建议时间复杂度:
O(n); - 额外空间复杂度:
O(n)。
示例
输出:[1,1,4,2,1,1,0,0]
输出:[1,1,1,0]
输出:[1,1,0]
数据约束
1 ≤ temperatures.length ≤ 10⁵30 ≤ temperatures[i] ≤ 100- 只有严格更高温度才能结束等待;相同温度不算。
已扫描但尚未遇到更高温度的日期。它们进入栈,继续等待未来信息。
栈保存索引而非温度,既能比较温度,也能计算等待天数。
栈中索引对应温度从栈底到栈顶单调不增。
历史日期被弹出时,当前日是它右侧第一个更暖日期,答案立即确定。
弹栈时只需记录“更大值是什么”。元素互不相同时,可以用值建立映射。
弹栈时还要计算等待天数,因此必须保存日期索引;索引同时决定答案写入位置和距离。
未解决日期栈 保存 index,不保存裸温度
answer 数组 出栈时写入 index 差
累计工作量
关键代码补全
代码与图像逐行联动
迁移题:LeetCode #901「股票价格跨度」
从离线数组转向在线数据流:每次调用 next(price) 都要立即返回今天向左连续、不高于今天价格的天数。
第一步:先读懂 #901,而不是直接套用单调栈模板
官方题目要求
设计一个接收每日股票价格的数据结构。对今天的价格 price,返回一个跨度:从今天向过去连续计算,价格小于或等于今天价格的最大连续天数。
约束
1 ≤ price ≤ 10⁵- 最多调用
next共10⁴次
官方示例
例如价格 75 到来时,向左连续的 60、70、60 都不高于 75,再加上今天,共 4 天。
不能预先遍历完整数组;一次只接收今天的价格。
即使昨天更高,今天自己的跨度也至少为 1。
相等价格也属于今天能够覆盖的连续区间。
每次 next 只返回今天的一个整数,而非最终数组。
读题检查 1:依次输入 100、80、60、70,next(70) 返回多少?
读题检查 2:连续两天价格都是 100,第二天跨度是多少?
第二步:#739 与 #901 复用同一个“弹栈归约”机制,但答案方向相反
#739 每日温度
current > stack_top#901 股票价格跨度
(price, compressed_span)stack_top_price <= current#901 为什么不能把栈项只写成价格?
第三步:把 #739 的索引栈逐项迁移为在线跨度栈
槽位 1 · 栈项保存什么?
今天需要复用历史已经计算出的连续区间。
槽位 2 · 今天的基础跨度
跨度必须包含今天自身。
槽位 3 · 哪些历史组可以被合并?
相等价格同样属于“不高于今天”。
槽位 4 · 如何保存并返回今天?
今天的价格与压缩跨度成为未来的一个整体。
拼装结果:黄色行是从 #739 迁移后发生语义变化的位置
第四步:逐次调用官方样例,观察跨度如何被压缩和复用
可选挑战:不复制参考答案,独立重写完整类
Unit 08 Skill 卡
单调栈不仅能寻找未来边界,也能压缩过去连续区间。#739 保存索引,在未来事件到来时给过去写距离;#901 保存 (price, span),在今天到来时把被支配的历史区间合并到今天。