【中等】739. 每日温度

0 阅读3分钟

给定一个整数数组 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 <= 105
  • 30 <= temperatures[i] <= 100

1. 生活案例:排队买奶茶

想象你在一家网红奶茶店排队:

  • 规则:每个人手里都有一个号码牌(代表温度)。你想知道,在你后面排队的人里,第一个比你号码大的人离你有多远。

  • 过程

    1. 你站在队伍里等。
    2. 新来一个人,如果他的号码比你,你也得继续等,他也得在你后面等。
    3. 新来一个人,如果他的号码比你,恭喜你!你等到了。你算出你们之间的距离(比如他是你后面第3个),然后你就可以拿着奶茶离开了。

这个“等待”的队伍,在编程里就是单调栈


2. 代码实现与详细注释

这是你图片中的代码,我为你加上了结合生活案例的详细中文注释:

JavaScript

/**
 * @param {number[]} temperatures - 每天的温度数组 (每个人手里的号码牌)
 * @return {number[]} - 返回一个数组,表示还要等几天才有更高温
 */
var dailyTemperatures = function(temperatures) {
    let stack = []; // 【等候区】:存放还没找到“更高温”的那些天的【下标】
    let n = temperatures.length;
    let result = new Array(n).fill(0); // 【结果单】:默认都是0,如果后面没等到的,就留作0

    for (let i = 0; i < n; i++) {
        // 当【等候区】有人,且【今天新来的温度】比【等候区最后一个人】的温度高时
        // 意味着等候区的人终于等到了他的“温暖”
        while (stack.length !== 0 && temperatures[i] > temperatures[stack[stack.length - 1]]) {
            
            // 1. 把等到了的那个人从等候区请出来 (出栈)
            let prevIndex = stack.pop(); 
            
            // 2. 计算那个人等了几天 (今天的下标 - 那人的下标)
            result[prevIndex] = i - prevIndex; 
            
            // 继续检查等候区里的前一个人,看看今天是不是也比他高
        }
        
        // 今天的温度暂时还没找到比它更高的,或者刚处理完别人,今天自己也要进【等候区】排队
        stack.push(i);
    }

    return result;
};

3. 核心原理解析

为什么用栈(Stack)?

  • 后进先出:在温度数组中,我们总是先拿“今天”的温度去和“最近还没找到更高温”的那几天比。
  • 保持单调性:在这个栈里,温度永远是从底到顶递减的。一旦来了一个高个子(高温),它就会把栈顶那些矮个子(低温)全部“解救”出来。

运行轨迹示例:

假设温度是 [73, 74, 75, 71, 69, 72]

  1. 73 进栈。

  2. 74 来了,比 73 高。73 出栈,记录结果:74(位置1) - 73(位置0) = 1。然后 74 进栈。

  3. 75 来了,比 74 高。74 出栈,记录结果:2 - 1 = 1。然后 75 进栈。

  4. 71 来了,比 75 低。71 进栈(等候区)。

  5. 69 来了,比 71 低。69 进栈(等候区)。此时栈里有:[75, 71, 69]

  6. 72 来了!

    • 69 高:69 出栈,计算 5 - 4 = 1
    • 71 高:71 出栈,计算 5 - 3 = 2
    • 75 低:72 进栈。

复杂度

  • 时间复杂度O(n)O(n)。虽然有嵌套循环,但每个元素最多进栈一次、出栈一次。
  • 空间复杂度O(n)O(n)。最坏情况下,所有温度都在栈里排队。

这种解法比暴力双循环(O(n2)O(n^2))快得多,尤其是在处理像 10 万条数据这种大规模输入时。