目录
过程解析
一、题目理解
给定一个数组,表示连续几天的气温。
要求输出一个同样长度的数组,其中第 i 个元素表示:
从第 i 天起,至少需要等待多少天 才会出现比第 i 天更高的温度 。
如果之后再也没有更高温度,则输出 0。
例如:
输入 73, 74, 75, 71, 69, 72, 76, 73
输出 1, 1, 4, 2, 1, 1, 0, 0
解释:
- 第 1 天(73)→ 下一天 74 更高 → 等 1 天;
- 第 2 天(74)→ 下一天 75 更高 → 等 1 天;
- 第 3 天(75)→ 要等到 76 (第 7 天)→ 等 4 天;
- ...依此类推。
二、核心思路
这题的关键在于:为每一天找到"右边第一个比它大的温度" 。
直接两层循环比对虽然能做,但时间复杂度是 O(n²),在数据量大时会超时。
于是可以使用一种经典的数据结构------单调栈(Monotonic Stack)。
三、单调栈思想
1. 栈的作用
我们维护一个栈,里面存放还没找到更高温度 的"天数下标"。
栈从底到顶保证:对应的温度是递减的。
2. 遍历数组的过程
当我们从左到右依次查看每一天时:
-
如果当天温度 ≤ 栈顶下标对应的温度:
表示当前还没有更高温度,把当天下标压入栈,等待后续更高的温度。
-
如果当天温度 > 栈顶下标对应温度:
说明当前这一天就是栈顶那天的"更高温度"。
我们可以计算两天的间隔天数:
当前天数索引 - 栈顶天数索引。
然后弹出栈顶,因为它已经找到了答案。
接着继续判断新的栈顶(可能连续几个更低温度都会被解决)。
这样,每个元素最多进栈一次、出栈一次,所以整个过程是 O(n) 的。
四、示例讲解
以输入数组:
73, 74, 75, 71, 69, 72, 76, 73
步骤演示
| 步骤 | 当前天数 | 当前温度 | 栈中下标(对应温度) | 操作 | 结果变化 |
|---|---|---|---|---|---|
| 1 | 0 | 73 | 栈为空,入栈 0 | 栈 → 0 | |
| 2 | 1 | 74 | 0(73) | 74 > 73,弹 0,ans0=1 | 栈 → 1 |
| 3 | 2 | 75 | 1(74) | 75 > 74,弹 1,ans1=1 | 栈 → 2 |
| 4 | 3 | 71 | 2(75) | 71 ≤ 75,入栈 3 | 栈 → 2, 3 |
| 5 | 4 | 69 | 2(75), 3(71) | 69 ≤ 71,入栈 4 | 栈 → 2, 3, 4 |
| 6 | 5 | 72 | 2(75), 3(71), 4(69) | 72 > 69 → 弹 4 (ans4=1),72 > 71 → 弹 3 (ans3=2),栈顶 75 > 72 → 停止,入 5 | 栈 → 2, 5 |
| 7 | 6 | 76 | 2(75), 5(72) | 76 > 72 → 弹 5 (ans5=1),76 > 75 → 弹 2 (ans2=4),栈空,入 6 | 栈 → 6 |
| 8 | 7 | 73 | 6(76) | 73 ≤ 76,入 7 | 栈 → 6, 7 |
遍历结束后,栈中 6 (76) 和 7 (73) 没有找到更高温度,保持默认值 0。
最终答案: 1, 1, 4, 2, 1, 1, 0, 0。
五、算法总结
-
算法类型:单调栈(递减栈)
-
时间复杂度:O(n)(每个元素最多进栈一次、出栈一次)
-
空间复杂度:O(n)(栈与答案数组所占空间)
-
适用场景:
- 寻找"右侧第一个比当前值更大/更小"的元素
- 常用于温度、股票、地形等类似问题
代码
C++
cpp
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
int count = temperatures.size();
vector<int> ans(count,0);
stack<int> st;
for(int i = 0;i<count;i++){
while(!st.empty()&&temperatures[i]>temperatures[st.top()]){
auto index = st.top();
st.pop();
ans[index] = i - index;
}
st.push(i);
}
return ans;
}
};
C语言
c
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* dailyTemperatures(int* temperatures, int temperaturesSize, int* returnSize) {
int* ans = (int*)calloc(temperaturesSize, sizeof(int));
int* stack = (int*)malloc(sizeof(int) * temperaturesSize);
int top = -1;
for (int i = 0; i < temperaturesSize; i++) {
while (top >= 0 && temperatures[i] > temperatures[stack[top]]) {
int index = stack[top--];
ans[index] = i - index;
}
stack[++top] = i;
}
*returnSize = temperaturesSize;
free(stack);
return ans;
}