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

一、题目概述

题目来源: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)

💬 一句话总结:

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

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

相关推荐
小欣加油1 小时前
leetcode 1018 可被5整除的二进制前缀
数据结构·c++·算法·leetcode·职场和发展
WWZZ20252 小时前
快速上手大模型:深度学习12(目标检测、语义分割、序列模型)
深度学习·算法·目标检测·计算机视觉·机器人·大模型·具身智能
Andrew_Ryan2 小时前
llama.cpp Build Instructions
算法
玖剹2 小时前
递归练习题(四)
c语言·数据结构·c++·算法·leetcode·深度优先·深度优先遍历
做人不要太理性2 小时前
【Linux系统】线程的同步与互斥:核心原理、锁机制与实战代码
linux·服务器·算法
向阳逐梦3 小时前
DC-DC Buck 电路(降压转换器)全面解析
人工智能·算法
Mz12213 小时前
day04 小美的区间删除
数据结构·算法
_OP_CHEN3 小时前
算法基础篇:(十九)吃透 BFS!从原理到实战,解锁宽度优先搜索的核心玩法
算法·蓝桥杯·bfs·宽度优先·算法竞赛·acm/icpc
小猪咪piggy3 小时前
【算法】day 20 leetcode 贪心
算法·leetcode·职场和发展