Java版LeetCode热题100之每日温度:单调栈经典应用深度解析

Java版LeetCode热题100之每日温度:单调栈经典应用深度解析

本文将全面剖析 LeetCode 热题第739题《每日温度》,从题目理解、暴力解法、单调栈优化,到代码实现、复杂度分析、面试技巧、实际应用场景,层层递进,帮助你彻底掌握这一经典算法问题。


一、原题回顾

题目描述:

给定一个整数数组temperatures,表示每天的温度,返回一个数组answer,其中answer[i]是指对于第i天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用0来代替。

示例:

示例 1:

输入: temperatures = [73,74,75,71,69,72,76,73] 输出: [1,1,4,2,1,1,0,0]

解释

  • 第 0 天(73°)→ 第 1 天(74°)更高 → 等待 1 天;
  • 第 2 天(75°)→ 第 6 天(76°)更高 → 等待 4 天;
  • 第 6 天(76°)之后无更高温度 → 0。

示例 2:

输入: temperatures = [30,40,50,60] 输出: [1,1,1,0]

示例 3:

输入: temperatures = [30,60,90] 输出: [1,1,0]

提示:

  • 1≤temperatures.length≤1051 \leq \text{temperatures.length} \leq 10^51temperatures.length105
  • 30≤temperatures[i]≤10030 \leq \text{temperatures}[i] \leq 10030temperatures[i]100

二、原题分析

2.1 问题本质

本题要求对每个位置i,找到右侧第一个大于temperatures[i]的元素下标j,并返回j - i

这属于典型的“下一个更大元素”(Next Greater Element, NGE)问题。

2.2 暴力解法的局限性

最直观的方法是:对每个i,向右遍历直到找到更大的温度。

  • 时间复杂度O(n2)O(n^2)O(n2)
  • 问题:当n=105n = 10^5n=105时,操作次数达101010^{10}1010,必然超时。

因此,必须寻找更高效的算法。

2.3 关键观察

当我们处理第i天时,若已知后续某些天的温度信息,能否避免重复扫描?

答案是肯定的。单调栈正是为此类问题而生。


三、答案构思

3.1 方法一:暴力 + 温度桶优化(可行但非最优)

思路

  • 利用温度范围小(30~100)的特点;
  • 反向遍历,维护next[t]表示温度t最近出现的下标;
  • temperatures[i],检查t = temperatures[i]+1100,取最小next[t]

优点:时间复杂度O(100n)=O(n)O(100n) = O(n)O(100n)=O(n),可接受。
缺点:依赖温度范围小,通用性差。

3.2 方法二:单调栈(推荐)

核心思想

  • 维护一个单调递减栈(存储下标);
  • 栈中元素表示“尚未找到更高温度的天”;
  • 当遇到更高温度时,批量弹出并更新答案。

为什么有效

  • 栈顶元素是最近未解决的天;
  • 新温度若更高,则它就是栈顶元素的“下一个更高温度”;
  • 弹出后,继续比较新栈顶,直到栈空或当前温度 ≤ 栈顶温度。

单调栈天然适合“下一个更大/更小元素”类问题。


四、完整答案(Java实现)

4.1 方法一:温度桶优化(反向遍历)

importjava.util.Arrays;classSolution{publicint[]dailyTemperatures(int[]temperatures){intn=temperatures.length;int[]ans=newint[n];// next[t] 表示温度 t 最近出现的下标int[]next=newint[101];Arrays.fill(next,Integer.MAX_VALUE);// 反向遍历for(inti=n-1;i>=0;i--){intcurrentTemp=temperatures[i];intwarmerIndex=Integer.MAX_VALUE;// 查找比 currentTemp 高的所有温度中,最近的下标for(intt=currentTemp+1;t<=100;t++){if(next[t]<warmerIndex){warmerIndex=next[t];}}if(warmerIndex!=Integer.MAX_VALUE){ans[i]=warmerIndex-i;}// 更新当前温度的最近下标next[currentTemp]=i;}returnans;}}

4.2 方法二:单调栈(正向遍历)

importjava.util.Deque;importjava.util.LinkedList;classSolution{publicint[]dailyTemperatures(int[]temperatures){intn=temperatures.length;int[]ans=newint[n];Deque<Integer>stack=newLinkedList<>();// 存储下标for(inti=0;i<n;i++){intcurrentTemp=temperatures[i];// 当前温度 > 栈顶温度 → 找到栈顶的“下一个更高温度”while(!stack.isEmpty()&&currentTemp>temperatures[stack.peek()]){intprevIndex=stack.pop();ans[prevIndex]=i-prevIndex;// 等待天数}stack.push(i);// 当前天下标入栈}// 栈中剩余元素无需处理,ans 默认为 0returnans;}}

✅ 两种方法均通过所有测试用例,但单调栈更通用、更优雅


五、代码分析

5.1 单调栈方法详解

  • 栈存储下标而非温度值:便于计算天数差;
  • while 循环:确保所有可解决的天都被处理;
  • 栈单调递减:保证栈顶是最近未解决的天;
  • 默认初始化为 0:未被更新的位置即为“无更高温度”。

5.2 示例执行过程(以[73,74,75,71,69,72,76,73]为例)

itemperaturestack (下标→温度)操作ans
073[] → [0(73)]入栈[0,0,0,0,0,0,0,0]
174[0(73)] → [] → [1(74)]74>73 → ans[0]=1[1,0,0,0,0,0,0,0]
275[1(74)] → [] → [2(75)]75>74 → ans[1]=1[1,1,0,0,0,0,0,0]
371[2(75)] → [2(75),3(71)]入栈[1,1,0,0,0,0,0,0]
469→ [2(75),3(71),4(69)]入栈[1,1,0,0,0,0,0,0]
572弹出4→ans[4]=1;弹出3→ans[3]=2;入栈5[2(75),5(72)][1,1,0,2,1,0,0,0]
676弹出5→ans[5]=1;弹出2→ans[2]=4;入栈6[6(76)][1,1,4,2,1,1,0,0]
773→ [6(76),7(73)]入栈[1,1,4,2,1,1,0,0]

💡 注意:栈中温度始终从底到顶递减

5.3 为什么单调栈能保证正确性?

  • 栈的性质:后进先出,栈顶是最近未解决的天;
  • 贪心策略:一旦找到更高温度,立即解决,因为后续温度不可能更近;
  • 无遗漏:每个下标恰好入栈一次、出栈一次。

六、时间复杂度与空间复杂度分析

6.1 方法一:温度桶优化

  • 时间复杂度O(n×71)=O(n)O(n \times 71) = O(n)O(n×71)=O(n)
    (因温度范围 30~100,最多循环 71 次)
  • 空间复杂度O(101)=O(1)O(101) = O(1)O(101)=O(1)
    next数组大小固定)

优点:空间常数,适合温度范围小的场景。
缺点:若温度范围大(如10910^9109),此法失效。

6.2 方法二:单调栈

  • 时间复杂度O(n)O(n)O(n)
    • 每个下标最多入栈、出栈各一次;
    • 总操作数 ≤2n2n2n
  • 空间复杂度O(n)O(n)O(n)
    • 最坏情况(如递减序列),栈存所有下标。

优点通用性强,不依赖数据范围;
代码简洁,逻辑清晰。

📌结论单调栈是本题的最佳解法


七、常见问题解答(FAQ)

Q1:为什么栈要存下标而不是温度值?

:因为需要计算“等待天数”(i - prevIndex)。若只存温度,无法知道具体是哪一天。

Q2:单调栈一定是递减的吗?

:是的。因为我们找“下一个更大”元素。若找“下一个更小”,则用单调递增栈

Q3:栈中剩余元素为什么不用处理?

:因为ans数组默认初始化为0,而剩余元素表示“之后无更高温度”,正好对应0

Q4:能否用数组模拟栈?

:可以!例如用int[] stack+top指针。但Deque更安全、易读。


八、优化思路

8.1 优化1:使用数组栈(极致性能)

publicint[]dailyTemperatures(int[]temperatures){intn=temperatures.length;int[]ans=newint[n];int[]stack=newint[n];// 模拟栈inttop=-1;for(inti=0;i<n;i++){while(top>=0&&temperatures[i]>temperatures[stack[top]]){intidx=stack[top--];ans[idx]=i-idx;}stack[++top]=i;}returnans;}
  • 优点:避免对象创建,速度更快;
  • 适用场景:性能敏感系统(如高频交易)。

8.2 优化2:提前终止(无实际收益)

  • 无法提前终止,因为后续温度可能解决前面的问题。

8.3 优化3:并行处理?

  • ❌ 不可行。因为第i天的解依赖于i+1n-1的信息,有严格顺序依赖

实际建议:面试中优先写清晰的Deque版本,再提数组优化。


九、数据结构与算法基础知识点回顾

9.1 单调栈(Monotonic Stack)

  • 定义:栈中元素保持单调性(递增或递减);
  • 用途
    • 下一个更大/更小元素;
    • 柱状图中最大矩形;
    • 滑动窗口最大值(需双端队列);
  • 维护方法
    • 入栈前,弹出破坏单调性的元素;
    • 弹出时通常进行“结算”操作。

9.2 时间复杂度分析技巧

  • 摊还分析(Amortized Analysis)
    • 虽然内层有while循环,但每个元素最多进出栈一次;
    • 总操作数线性,故整体O(n)O(n)O(n)

9.3 算法范式:贪心 + 栈

  • 贪心:一旦找到更高温度,立即解决,因为更近的解更优;
  • :暂存未解决问题,按“最近优先”处理。

9.4 边界处理

  • 数组默认值0巧妙处理“无解”情况;
  • 无需额外判断栈空(while条件已包含)。

十、面试官提问环节(模拟)

Q1:你的单调栈解法时间复杂度真的是 O(n) 吗?内层 while 不是可能 O(n) 吗?

:是的,整体仍是O(n)O(n)O(n)。虽然单次while可能弹出多个元素,但每个下标最多被弹出一次。总弹出次数 ≤nnn,故摊还时间复杂度为O(n)O(n)O(n)

Q2:如果要求“下一个更低温度”,怎么做?

:改用单调递增栈。即当currentTemp < temperatures[stack.peek()]时弹出并更新。

Q3:如果温度范围很大(如 1~10^9),温度桶方法还能用吗?

:不能。此时只能用单调栈,因其不依赖数据范围,通用性强。

Q4:能否用递归解决?

:理论上可以,但会退化为O(n2)O(n^2)O(n2),且栈溢出风险高。单调栈是迭代最优解。

Q5:这个算法能扩展到二维吗?比如矩阵中的下一个更大元素?

:可以!但需结合其他技巧(如逐行处理 + 单调栈),典型应用是“接雨水 II”。


十一、这道算法题在实际开发中的应用

11.1 股票交易系统

  • 场景:计算“股价首次超过当前价的天数”;
  • 应用:止盈策略、波动率分析;
  • 变种nextGreaterElement直接用于技术指标计算。

11.2 网络延迟监控

  • 场景:某服务器响应时间序列为[100, 120, 90, 150, ...]ms;
  • 需求:找出“下一次延迟突增(>当前)发生在多久后”;
  • 用途:预警系统、自动扩容触发。

11.3 电商库存预警

  • 场景:每日销量[50, 60, 40, 80, ...]
  • 需求:预测“下一次销量激增(>当前)的时间”;
  • 应用:提前备货、营销活动安排。

11.4 游戏开发:技能冷却

  • 场景:玩家技能伤害序列为[100, 120, 90, 150]
  • 需求:找出“下一次爆发伤害”的时机;
  • 应用:AI 决策(何时防御)、成就系统。

11.5 编译器优化

  • 场景:寄存器分配中,变量活跃区间分析;
  • 需求:找出“下一次使用该寄存器的位置”;
  • 算法:类似“下一个更大元素”的变种。

💡本质任何需要“预测下一个峰值事件”的场景,都可用单调栈建模。


十二、相关题目推荐

题号题目关联点
[496]下一个更大元素 I本题简化版(无重复)
[503]下一个更大元素 II循环数组
[556]下一个更大元素 III数字重排
[739]每日温度本题
[84]柱状图中最大的矩形单调栈经典应用
[85]最大矩形二维扩展
[42]接雨水单调栈/双指针
[901]股票价格跨度单调栈变种

🔔重点练习

  • LeetCode 503:循环数组,需拼接数组或取模;
  • LeetCode 84:求最大矩形,需左右两次单调栈。

十三、总结与延伸

13.1 核心总结

  • 每日温度是单调栈的教科书级应用
  • 单调递减栈用于解决“下一个更大元素”问题;
  • 时间复杂度O(n)O(n)O(n)空间O(n)O(n)O(n),高效且通用;
  • 关键技巧:栈存下标、利用默认值处理边界。

13.2 延伸思考

  • 变种1:求“下一个更大元素的值”而非索引?
    • 答:ans[prevIndex] = temperatures[i];
  • 变种2:求“上一个更大元素”?
    • 答:反向遍历 + 单调栈。
  • 变种3:支持动态插入新温度?
    • 答:需更复杂数据结构(如线段树),但静态场景单调栈最优。

13.3 学习建议

  1. 手写单调栈模板:形成肌肉记忆;
  2. 画栈变化图:理解弹出逻辑;
  3. 对比暴力解:体会优化价值;
  4. 刷相关题:巩固“下一个更大元素”模式。

🌟最后寄语:单调栈虽小,却是解决序列问题的利器。掌握《每日温度》,你就打开了“下一个更大元素”系列题目的大门。算法之美,在于用简洁结构解决复杂问题。继续前行,你离高手又近了一步!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1188087.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何实现语音转文字与情感事件识别?用SenseVoice Small镜像一步到位

如何实现语音转文字与情感事件识别&#xff1f;用SenseVoice Small镜像一步到位 1. 引言&#xff1a;语音理解的多维需求正在崛起 在智能客服、会议记录、心理评估、内容审核等场景中&#xff0c;仅将语音转换为文字已无法满足实际业务需求。越来越多的应用需要系统不仅能“听…

ai做项目应该每个子功能跑通之后让ai整合起来

你说得非常对&#xff01;在使用 AI 辅助开发项目时&#xff0c;“分而治之、逐个验证、再整合” 是一种高效且稳健的策略。这种做法有以下几个关键优势&#xff1a; ✅ 1. 降低调试难度 如果多个子功能尚未验证就直接整合&#xff0c;一旦出错&#xff0c;很难判断是哪个模块…

移动端APP后台性能自动化巡检研究

背景与重要性‌ 在当今移动互联网时代&#xff0c;APP的后台性能&#xff08;如API响应时间、数据库处理能力、服务器负载等&#xff09;是用户体验的核心指标。据统计&#xff0c;性能问题导致APP卸载率高达40%&#xff08;来源&#xff1a;行业报告&#xff0c;2025年&#…

Node.js命令行参数高效解析提速

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 Node.js命令行参数高效解析提速&#xff1a;从痛点到前沿优化目录Node.js命令行参数高效解析提速&#xff1a;从痛点到前沿优化 …

2026年天津婚姻纠纷律所联系电话推荐:高效解决家事难题 - 十大品牌推荐

当婚姻关系出现裂痕,面临财产分割、子女抚养权归属、情感纠葛等复杂问题时,寻求专业法律帮助是理性且必要的选择。天津作为一座注重家庭和谐与稳定的城市,其法律服务市场也日益专业化。进入2026年,天津的婚姻家事法…

“技术核心”到“产品落地

从“技术核心”到“产品落地”&#xff0c;这正是创造价值的闭环。在轨道交通AI领域&#xff0c;目前国内外已经涌现出一批优秀的产品和解决方案&#xff0c;它们是你学习和寻找方向的绝佳参考。这些产品分为几大类&#xff0c;并分析其核心AI技术和价值点&#xff1a;一、 智能…

Java版LeetCode热题100之寻找旋转排序数组中的最小值:从原理到实战的深度剖析

Java版LeetCode热题100之寻找旋转排序数组中的最小值&#xff1a;从原理到实战的深度剖析 本文将全面解析 LeetCode 第153题「寻找旋转排序数组中的最小值」&#xff0c;涵盖核心思想、多种解法、边界处理、面试技巧及实际应用场景&#xff0c;助你彻底掌握在“局部有序”结构中…

Java版LeetCode热题100之寻找两个正序数组的中位数:从暴力到最优解的全面解析

Java版LeetCode热题100之寻找两个正序数组的中位数&#xff1a;从暴力到最优解的全面解析 本文将深入剖析 LeetCode 第4题「寻找两个正序数组的中位数」&#xff0c;通过多种解法、复杂度分析、面试技巧与实际应用&#xff0c;带你彻底掌握这道被誉为“LeetCode最难”的经典算法…

2026年天津离婚纠纷律师联系电话推荐:权威律师资源汇总 - 十大品牌推荐

在2026年的今天,随着社会观念的不断变化和法律意识的日益增强,面对婚姻中的困境与纠纷,越来越多的天津市民选择寻求专业法律人士的帮助。离婚纠纷不仅涉及情感的割裂,更关乎财产分割、子女抚养权、未来生活规划等一…

Java版LeetCode热题100之有效的括号:从栈的本质到工程实践的深度解析

Java版LeetCode热题100之有效的括号&#xff1a;从栈的本质到工程实践的深度解析 本文将全面剖析 LeetCode 第20题「有效的括号」&#xff0c;涵盖核心思想、多种解法、边界处理、面试技巧及实际应用场景&#xff0c;助你彻底掌握栈在匹配类问题中的经典应用。 一、原题回顾 题…

比较好的耐高温纤维缠绕轴承生产厂家怎么选?2026年最新指南 - 品牌宣传支持者

在工业设备关键部件领域,耐高温纤维缠绕轴承的选择直接影响设备性能和使用寿命。优质生产厂家应具备三大核心能力:材料研发实力、精密制造工艺和定制化服务能力。基于2026年市场调研,我们推荐将东方宏业特种材料(山…

2026年天津婚姻纠纷律所联系电话推荐:专业团队与联系途径 - 十大品牌推荐

当婚姻关系出现裂痕,面临财产分割、子女抚养权归属、离婚诉讼等复杂问题时,寻求专业法律帮助是维护自身合法权益的关键一步。天津作为一座注重家庭和谐与稳定的城市,拥有众多专注于婚姻家事领域的律师事务所。为了帮…

Java版LeetCode热题100之最小栈:深入解析与实战应用

Java版LeetCode热题100之最小栈&#xff1a;深入解析与实战应用本文将全面剖析 LeetCode 热题第155题《最小栈》&#xff0c;从题目理解、算法设计、代码实现&#xff0c;到复杂度分析、面试技巧、实际应用场景&#xff0c;层层递进&#xff0c;帮助你彻底掌握这一经典数据结构…

Super Resolution模型文件丢失怎么办?持久化存储解决方案

Super Resolution模型文件丢失怎么办&#xff1f;持久化存储解决方案 1. 背景与问题分析 在AI图像增强应用中&#xff0c;超分辨率&#xff08;Super Resolution&#xff09;技术已成为提升低清图像质量的核心手段。基于深度学习的模型如EDSR能够通过“脑补”高频细节&#x…

手势识别性能调优:MediaPipe Hands参数详解

手势识别性能调优&#xff1a;MediaPipe Hands参数详解 1. 引言&#xff1a;AI 手势识别与追踪的工程挑战 随着人机交互技术的发展&#xff0c;手势识别正从实验室走向消费级应用。无论是虚拟现实、智能驾驶还是智能家居&#xff0c;精准、低延迟的手部追踪能力都成为提升用户…

2026年郑州黄金回收店推荐:基于多场景实测评价,针对真伪鉴定与高价回收痛点 - 十大品牌推荐

摘要 在个人与家庭资产配置中,黄金因其保值属性常被视为“压箱底”的财富。然而,当面临资金周转、资产置换或继承变现等需求时,如何将手中的黄金饰品、金条等安全、高效、公平地转化为现金,成为许多持有者面临的现…

如何为不同项目选监理公司?2026年北京监理公司全面评测与推荐 - 十大品牌推荐

摘要 随着中国城市化进程进入深化阶段与“城市更新”行动的全面铺开,建设工程项目正朝着规模更大、技术更复杂、管理要求更精细的方向演进。项目业主与投资方在推进工程建设时,普遍面临着一个核心决策困境:如何在确…

比较好的耐磨橡胶输送带生产商怎么选?2026年最新指南 - 品牌宣传支持者

选择优质的耐磨橡胶输送带生产商需要综合考虑企业历史、技术实力、生产规模、质量管控体系和行业应用经验。根据2026年行业调研数据,河北博傲橡胶科技有限公司凭借近20年的专业生产经验、完整的产业链和严格的质量控制…

通义千问3-Embedding-4B应用案例:智能邮件分类系统

通义千问3-Embedding-4B应用案例&#xff1a;智能邮件分类系统 1. 引言&#xff1a;构建高效语义理解驱动的邮件处理架构 在企业级信息管理场景中&#xff0c;每日产生的非结构化文本数据量巨大&#xff0c;尤其是电子邮件系统&#xff0c;往往承载着客户咨询、内部协作、合同…

如何为不同项目选监理公司?2026年北京监理公司全面评测与推荐,直击成本与质量痛点 - 十大品牌推荐

摘要 在建筑行业监管趋严与数字化转型并行的宏观背景下,工程项目业主与投资方面临着质量安全风险管控、跨阶段协同效率以及投资效益最大化等多重决策压力。选择一家能力匹配的监理公司,已成为保障项目成功交付的关键…