# 「力扣」第 739 题:每日温度(中等)

# 题目描述

请根据每日 气温 列表 temperatures ,请计算在每一天需要等几天才会有更高的温度。如果气温在这之后都不会升高,请在该位置用 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 <= 10^5
  • 30 <= temperatures[i] <= 100

# 方法一:暴力解法(Brute Force)

参考代码 1

import java.util.Arrays;

public class Solution {

    public int[] dailyTemperatures(int[] T) {
        int len = T.length;
        if (len < 2) {
            return new int[len];
        }

        int[] res = new int[len];
        res[len - 1] = 0;
        for (int i = 0; i < len - 1; i++) {
            int curVal = T[i];
            for (int j = i + 1; j < len; j++) {
                if (T[j] > curVal) {
                    res[i] = j - i;
                    break;
                }
            }
        }
        return res;
    }

    public static void main(String[] args) {
        int[] T = {73, 74, 75, 71, 69, 72, 76, 73};
        Solution solution = new Solution();
        int[] res = solution.dailyTemperatures(T);
        System.out.println(Arrays.toString(res));
    }
}

复杂度分析

  • 时间复杂度:,这里 表示 T 数组的长度。
  • 空间复杂度:

# 方法二:栈(单调栈)

  • 根据经验「找出右边第 1 个严格大于自己的元素的下标」,这件事情可以通过「栈」完成计算,并且维护这个栈的单调性;
  • 这里需要分析出「后进先出」的规律:栈顶元素出栈,表示栈顶元素找到了「右边第 1 个严格大于自己的元素」(就是当前遍历到的元素 i)。

总结:

  • 单调栈专门解决「找左边(或者右边)第 1 个严格大于自己的元素」;
  • 这里的单调栈从栈底到栈顶是一个单调不增栈,遇到值相同的元素的时候,仍然要入栈;
  • 存的是下标,拿出来以后,还要从 T 中取值;
  • 以下两点是始终保持的:
    • 因为一个元素对应的结果,要靠还没有入栈的元素的值确定,因此在遍历的时候,一定有一个元素入栈;
    • 出栈的时候,出栈元素的结果可以确定。

参考代码 2

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.Stack;

public class Solution {

    public int[] dailyTemperatures(int[] T) {
        int len = T.length;
        if (len < 2) {
            return new int[len];
        }

        int[] res = new int[len];
        // 栈里存下标;对应的值的特点,单调不增;出栈的时候,记录 res
        Deque<Integer> stack = new ArrayDeque<>();
        for (int i = 0; i < len; i++) {
            while (!stack.isEmpty() && T[stack.peekLast()] < T[i]) {
                int index = stack.removeLast();
                res[index] = i - index;
            }
            stack.addLast(i);
        }

        // 最后在栈里的元素保持单调不增,因此下面这三行代码可以省略
        while (!stack.isEmpty()) {
            res[stack.pop()] = 0;
        }
        return res;
    }
}

复杂度分析

  • 时间复杂度:,扫描一次 T 数组就可以得到答案,可以认为是以空间换时间;
  • 空间复杂度:

参考代码 3

  • 由于维护单调不减栈,可以在一开始放置一个很大的数值,使得站内元素永远非空。
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;

public class Solution {

    public int[] dailyTemperatures(int[] T) {
        int len = T.length;

        int[] newT = new int[len + 1];
        newT[0] = Integer.MAX_VALUE;
        for (int i = 0; i < len; i++) {
            newT[i + 1] = T[i];
        }

        int[] res = new int[len];
        T = newT;

        Deque<Integer> stack = new ArrayDeque<>();
        stack.addLast(0);

        // 注意有效位置从 1 开始
        for (int i = 1; i <= len; i++) {
            // 由于有哨兵结点在,查看栈顶元素的时候不用判空
            while (T[stack.peekLast()] < T[i]) {
                Integer top = stack.removeLast();
                res[top - 1] = i - top;
            }
            stack.addLast(i);
        }
        return res;
    }
}

复杂度分析:(同上)


作者:liweiwei1419 链接:https://suanfa8.com/stack/solutions-2/0739-daily-temperatures 来源:算法吧 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Last Updated: 11/19/2024, 1:33:17 AM