从零开始刷算法-单调栈-每日温度

一、题目概述

题目来源:LeetCode 739 - Daily Temperatures

题目要求:

给定一个整数数组 temperatures,表示每天的温度,返回一个数组 answer,其中 answer[i] 表示距离第 i 天之后,温度升高所需要的天数。如果之后没有更高的温度,则 answer[i] = 0

示例:

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

二、思路分析

这道题的核心在于:

对于每一天 i,要找到右边第一个比它温度高的那一天

如果我们暴力查找,每个 i 都向右扫描,复杂度是 O(n^2),显然不行。

于是可以考虑使用一个**单调栈(Monotonic Stack)**来优化。


三、单调栈思路讲解

1️⃣ 从后往前遍历的原因

我们从右往左遍历数组,因为:

  • 当前天的右边温度都已经处理完;

  • 栈中存放的下标对应的温度都是"右边的天",

  • 所以可以直接用栈顶判断"右边第一个更高温度"。

2️⃣ 栈中存什么?

栈中存放的是 下标 i ,而不是温度值。

因为要计算天数差(st.top() - i)。

3️⃣ 如何维护栈的单调性?

我们希望栈中的温度是递减的(栈顶最小)。

  • 当前温度 t 如果比栈顶温度高,说明栈顶那天不可能成为任何左边天的答案,直接 pop 掉;

  • 否则说明栈顶那天温度比当前天高,可以计算答案。

4️⃣ 状态更新逻辑

伪代码逻辑如下:

cpp 复制代码
for i 从右往左:
    当前温度 = t[i]
    while 栈不空 && 当前温度 >= 栈顶温度:
        弹栈(因为这些天对答案没贡献)
    if 栈不空:
        ans[i] = 栈顶下标 - i
    压入当前下标 i

四、完整代码实现

cpp 复制代码
class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        int n = temperatures.size();
        vector<int> ans(n);
        stack<int> st;  // 单调递减栈,存放下标

        for (int i = n - 1; i >= 0; i--) {
            int t = temperatures[i];
            while (!st.empty() && t >= temperatures[st.top()]) {
                st.pop();
            }
            if (!st.empty()) {
                ans[i] = st.top() - i;
            }
            st.push(i);
        }

        return ans;
    }
};

五、运行流程示例

以输入 [73,74,75,71,69,72,76,73] 为例:

i 温度 栈中下标(从栈底到栈顶) 栈中对应温度 ans[i] 说明
7 73 [7] [73] 0 栈空,压入
6 76 [] [] 0 76>73,弹出后压入
5 72 [6,5] [76,72] 1 栈顶温度76更高
4 69 [6,5,4] [76,72,69] 1 栈顶温度72更高
3 71 [6,5,3] [76,72,71] 2 下一个高温是72
2 75 [6,2] [76,75] 4 下一个高温是76
1 74 [6,2,1] [76,75,74] 1 下一个高温是75
0 73 [6,2,1,0] [76,75,74,73] 1 下一个高温是74

六、复杂度分析

  • 时间复杂度: O(n),每个元素最多被压栈和弹栈一次。

  • 空间复杂度: O(n),栈最多存储 n 个下标。


七、总结

特点 说明
遍历方向 从右往左更自然
栈结构 单调递减栈
栈中存储 温度下标
逻辑核心 弹出无用天,栈顶即为最近更高温度
时间复杂度 O(n)

💬 一句话总结:

单调栈的关键不是"栈"本身,而是"单调性"带来的剪枝。

我们用栈保证每次处理时,能立刻找到"右边第一个更大元素"。

相关推荐
老鼠只爱大米4 小时前
LeetCode经典算法面试题 #295:数据流的中位数(双堆法、有序列表、平衡树等多种实现方案详解)
算法·leetcode·优先队列··数据流·中位数·java 面试题
x_xbx4 小时前
LeetCode:215. 数组中的第K个最大元素
数据结构·算法·leetcode
黎阳之光4 小时前
AI数智筑防线 绿色科技启新篇——黎阳之光硬核技术赋能生态安全双升级
大数据·人工智能·算法·安全·数字孪生
2501_924952694 小时前
C++中的过滤器模式
开发语言·c++·算法
2401_873204654 小时前
C++中的组合模式实战
开发语言·c++·算法
西野.xuan4 小时前
内存布局(堆vs栈)一篇详解!!
java·数据结构·算法
2401_831824964 小时前
高性能压缩库实现
开发语言·c++·算法
2401_874732535 小时前
C++中的策略模式进阶
开发语言·c++·算法
大熊背5 小时前
ISP离线模式应用(二)-如何利用 ISP 离线模式 加速 3DNR 收敛
linux·算法·rtos·isp pipeline·3dnr
zhangfeng11335 小时前
`transformers` 的 `per_device_train_batch_size` 不支持小于 1 的浮点数值,llamafactory 支持
人工智能·算法·batch