题目描述

✅ LCR 038. 每日温度

image-20260928235607559

题意分析

对每一天 i,找到右侧第一个满足 temperatures[j] > temperatures[i] 的位置 j,返回等待天数 j - i;找不到时返回 $0$。温度必须严格更高,相等不能作为答案。

每天分别向右扫描,最坏需要 $O(n^2)$ 时间。可以把尚未找到答案的日期集中保存,让新的一天一次解决所有能被它满足的等待者。

解法:单调栈维护候选

核心思路

[!blue]

栈中保存尚未遇到更高温度的下标,下标从栈底到栈顶递增,对应温度单调不增。存下标既能查回温度,也能在找到答案时计算相隔天数。

扫描到第 i 天,只要今天温度严格高于栈顶那天,就弹出下标 j,令 answer[j] = i - j。今天可能同时满足多个等待者,因此要连续弹栈。若栈顶温度已不低于今天,栈内更下面的温度也不低于今天,便可以停止,再把 i 入栈。

弹出时得到的一定是第一个更高温度:从 j 到 i 之间的日期都已按顺序处理,若此前出现过更高温度,j 早就会被结算,不可能还留在栈中。弹完后栈顶温度不小于今天,再压入 i,也保持了单调不增的性质。

相等温度要同时留栈,等待之后真正升温。扫描结束仍在栈中的日期没有更高温度,答案保留数组初始值 $0$;最后一天也一定为 $0$。

解题步骤

  1. 创建全零的结果数组和空下标栈。
  2. 从左到右扫描,每当当前温度高于栈顶温度,就弹出下标并写入下标差。
  3. 重复弹栈,直到栈空或栈顶温度不低于当前温度。
  4. 将当前下标入栈,继续处理下一天。
  5. 返回结果,无需再次清空栈。严格递增时除最后一天外答案均为 $1$;严格递减或全相等时答案均为 $0$。

代码实现

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        int n = temperatures.length;
        // 默认全 0,正好对应「之后再无更高温度」。
        int[] answer = new int[n];
        // 栈里存下标,温度自底向上单调不增,含义是「还没等到更高温度的日子」。
        Deque<Integer> stk = new ArrayDeque<>();

        for (int i = 0; i < n; ++i) {
            // 严格小于才结算,相同温度不算「更高」。
            while (!stk.isEmpty() && temperatures[stk.peek()] < temperatures[i]) {
                int j = stk.pop();

                answer[j] = i - j;
            }

            stk.push(i);
        }

        return answer;
    }
}
func dailyTemperatures(temperatures []int) []int {
    // 默认全 0,正好对应「之后再无更高温度」。
    answer := make([]int, len(temperatures))
    // 栈里存下标,温度自底向上单调不增。
    var stk []int
    for i, t := range temperatures {
        // 严格小于才结算,相同温度不算「更高」。
        for len(stk) > 0 && temperatures[stk[len(stk)-1]] < t {
            j := stk[len(stk)-1]
            answer[j] = i - j
            stk = stk[:len(stk)-1]
        }
        stk = append(stk, i)
    }
    return answer
}

复杂度分析

  • 时间复杂度:$O(n)$。每个下标入栈一次、至多出栈一次,所有内层循环的弹栈次数合计不超过 $n$。
  • 空间复杂度:$O(n)$,不计结果数组。温度持续不升时,所有下标都会留在栈中。

关键点总结

[!green]

  • 栈保存未解决的日期,温度从栈底到栈顶单调不增。
  • 当前温度严格更高才结算,弹出时直接得到最近的升温日。
  • 每个下标只结算一次,剩余答案保持 $0$。

易错点总结

[!yellow]

  • 栈存下标,弹栈后才能用当前下标减旧下标计算等待天数。
  • 只有严格升温才弹栈,相同温度继续等待。
  • 先结算所有更低温的栈顶,再将当前下标入栈;先入栈会挡住旧候选。

相似题目

题目 难度 关联与区别
496. 下一个更大元素 I 简单 同样寻找右侧第一个更大元素,本题返回距离,所以栈中保存下标。
503. 下一个更大元素 II 中等 原题数组首尾相接,需要再次扫描来补足跨边界的更大值,本题只向右查找。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/78184662
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!