2026/3/24 5:08:37
网站建设
项目流程
视频网站设计模板,深圳建筑设计师招聘,网站怎么找的,建设通appJava版LeetCode热题100之每日温度#xff1a;单调栈经典应用深度解析本文将全面剖析 LeetCode 热题第739题《每日温度》#xff0c;从题目理解、暴力解法、单调栈优化#xff0c;到代码实现、复杂度分析、面试技巧、实际应用场景#xff0c;层层递进#xff0c;帮助你彻底…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^51≤temperatures.length≤10530≤temperatures[i]≤10030 \leq \text{temperatures}[i] \leq 10030≤temperatures[i]≤100二、原题分析2.1 问题本质本题要求对每个位置i找到右侧第一个大于temperatures[i]的元素下标j并返回j - i。这属于典型的“下一个更大元素”Next Greater Element, NGE问题。2.2 暴力解法的局限性最直观的方法是对每个i向右遍历直到找到更大的温度。时间复杂度O(n2)O(n^2)O(n2)问题当n105n 10^5n105时操作次数达101010^{10}1010必然超时。因此必须寻找更高效的算法。2.3 关键观察当我们处理第i天时若已知后续某些天的温度信息能否避免重复扫描答案是肯定的。单调栈正是为此类问题而生。三、答案构思3.1 方法一暴力 温度桶优化可行但非最优思路利用温度范围小30~100的特点反向遍历维护next[t]表示温度t最近出现的下标对temperatures[i]检查t temperatures[i]1到100取最小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){intntemperatures.length;int[]ansnewint[n];// next[t] 表示温度 t 最近出现的下标int[]nextnewint[101];Arrays.fill(next,Integer.MAX_VALUE);// 反向遍历for(intin-1;i0;i--){intcurrentTemptemperatures[i];intwarmerIndexInteger.MAX_VALUE;// 查找比 currentTemp 高的所有温度中最近的下标for(inttcurrentTemp1;t100;t){if(next[t]warmerIndex){warmerIndexnext[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){intntemperatures.length;int[]ansnewint[n];DequeIntegerstacknewLinkedList();// 存储下标for(inti0;in;i){intcurrentTemptemperatures[i];// 当前温度 栈顶温度 → 找到栈顶的“下一个更高温度”while(!stack.isEmpty()currentTemptemperatures[stack.peek()]){intprevIndexstack.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 (下标→温度)操作ans073[] → [0(73)]入栈[0,0,0,0,0,0,0,0]174[0(73)] → [] → [1(74)]7473 → ans[0]1[1,0,0,0,0,0,0,0]275[1(74)] → [] → [2(75)]7574 → 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)最坏情况如递减序列栈存所有下标。✅优点通用性强不依赖数据范围✅代码简洁逻辑清晰。结论单调栈是本题的最佳解法。七、常见问题解答FAQQ1为什么栈要存下标而不是温度值答因为需要计算“等待天数”i - prevIndex。若只存温度无法知道具体是哪一天。Q2单调栈一定是递减的吗答是的。因为我们找“下一个更大”元素。若找“下一个更小”则用单调递增栈。Q3栈中剩余元素为什么不用处理答因为ans数组默认初始化为0而剩余元素表示“之后无更高温度”正好对应0。Q4能否用数组模拟栈答可以例如用int[] stacktop指针。但Deque更安全、易读。八、优化思路8.1 优化1使用数组栈极致性能publicint[]dailyTemperatures(int[]temperatures){intntemperatures.length;int[]ansnewint[n];int[]stacknewint[n];// 模拟栈inttop-1;for(inti0;in;i){while(top0temperatures[i]temperatures[stack[top]]){intidxstack[top--];ans[idx]i-idx;}stack[top]i;}returnans;}优点避免对象创建速度更快适用场景性能敏感系统如高频交易。8.2 优化2提前终止无实际收益无法提前终止因为后续温度可能解决前面的问题。8.3 优化3并行处理❌ 不可行。因为第i天的解依赖于i1到n-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 学习建议手写单调栈模板形成肌肉记忆画栈变化图理解弹出逻辑对比暴力解体会优化价值刷相关题巩固“下一个更大元素”模式。最后寄语单调栈虽小却是解决序列问题的利器。掌握《每日温度》你就打开了“下一个更大元素”系列题目的大门。算法之美在于用简洁结构解决复杂问题。继续前行你离高手又近了一步