题目描述
给定一个整数数组temperatures,表示每天的温度,返回一个数组answer,其中answer[i]是指对于第i天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用0来代替。
示例 1:
输入:temperatures = [73,74,75,71,69,72,76,73]输出:[1,1,4,2,1,1,0,0]
示例 2:
输入:temperatures = [30,40,50,60]输出:[1,1,1,0]
示例 3:
输入:temperatures = [30,60,90]输出:[1,1,0]
提示:
1 <= temperatures.length <= 10530 <= temperatures[i] <= 100
解决方案:
这段代码是基于单调栈求解 “每日温度” 问题的经典逆序遍历实现,核心思路是从后往前遍历温度数组,利用栈记录未找到更高温度的下标,通过维护栈的单调递减特性,快速找到每个位置下一个更高温度的天数。
核心逻辑
核心定义:
ans:结果数组,ans[i]表示第i天需要等待多少天才能遇到更高温度,初始值默认为 0;t_num:单调栈(存储数组下标),栈内下标对应的温度严格单调递减,用于记录后续未被匹配的 “更高温度候选位置”。
遍历方式:从数组末尾(
i=len-1)向前遍历,逆序处理能让每个元素仅入栈 / 出栈一次,保证时间效率。单调栈核心操作:
- 对于当前下标
i的温度tmp:①清理无效元素:循环弹出栈顶元素,直到栈为空或栈顶下标对应的温度 >tmp(这些栈顶元素的温度≤当前温度,无法成为当前位置的 “更高温度”,需剔除);②计算结果:若栈非空,说明栈顶下标是当前位置的下一个更高温度位置,ans[i] = 栈顶下标 - i;若栈空,ans[i]保持 0(无更高温度);③入栈当前下标:将i压入栈,作为前面位置的 “更高温度候选”。
- 对于当前下标
结果返回:遍历完成后,
ans数组即为每个位置对应的等待天数,直接返回。
关键特点
- 时间复杂度 O (n):每个元素仅入栈、出栈各一次,无嵌套循环的额外开销;
- 空间复杂度 O (n):栈最多存储所有下标(最坏情况温度单调递减),结果数组为 O (n);
- 单调栈特性:栈内下标对应的温度始终保持单调递减,确保能快速找到 “下一个更高温度”;
- 逆序优势:逆序遍历让后续的 “更高温度” 先入栈,当前位置只需对比栈顶即可,逻辑更简洁。
验证示例(以temperatures = [73,74,75,71,69,72,76,73]为例)
- 遍历到 73(i=7):栈空→ans [7]=0,入栈 7;
- 遍历到 76(i=6):栈顶 7 对应 73≤76→弹出,栈空→ans [6]=0,入栈 6;
- 遍历到 72(i=5):栈顶 6 对应 76>72→ans [5]=6-5=1,入栈 5;
- 最终
ans = [1,1,4,2,1,1,0,0],与预期结果一致。
总结
- 核心思路:逆序遍历 + 单调栈,利用栈的单调性快速匹配 “下一个更高温度”,避免暴力遍历的 O (n²) 复杂度;
- 关键设计:栈存储下标而非温度值,既保留温度对比能力,又能直接计算天数差;
- 功能效果:是 “下一个更大元素” 类问题的最优解法,能高效处理任意长度的温度数组。
函数源码:
class Solution { public: vector<int> dailyTemperatures(vector<int>& temperatures) { int len=temperatures.size(); vector<int> ans(len); stack<int> t_num={}; for(int i=len-1;i>=0;i--){ int tmp=temperatures[i]; while(!t_num.empty() && tmp>=temperatures[t_num.top()]){ t_num.pop(); } if(!t_num.empty()){ ans[i]=t_num.top()-i; } t_num.push(i); } return ans; } };