【算法思考记录】力扣739. 每日温度【单调栈,Java,Python3,C++】

原题链接


单调栈解决每日温度问题

本文旨在通过详细解析算法题739 - “每日温度”,演示如何利用单调栈结构高效解决实际问题。题目要求根据每天的温度,计算出距离下一次温度升高所需的天数。本文将提供Python、C++和Java三种语言实现的代码,并对解题思路和单调栈的应用进行深入分析。

题目概述

给定一个整数数组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. 单调性: 栈内元素保持严格的单调递增或递减顺序。通常,单调递增栈用于找出元素的“下一个更小值”,而单调递减栈用于找出元素的“下一个更大值”。

  2. 栈操作: 在处理每个元素时,会进行入栈和出栈操作。当遇到破坏单调性的元素时,会进行连续的出栈操作,直到恢复栈的单调性为止,然后再将新元素入栈。

应用场景

单调栈适用于各种需要查询元素之间特定关系的问题,如:

  • 在一个数组中,寻找每个元素右侧第一个比它大(或小)的元素。
  • 计算数组中每个元素向左延伸和向右延伸的距离,如在直方图中找到每个条形图能扩展的最大宽度。
  • 某些字符串匹配和处理问题,其中元素的顺序和它们之间的相对位置很重要。
算法特点
  • 高效性: 单调栈算法通常能够以线性时间复杂度处理问题,因为每个元素最多被压入和弹出栈一次。
  • 直观: 算法实现相对简洁直观,便于理解和应用。
  • 适用范围有限: 单调栈不是通用解决方案,它只适用于能够通过维护序列中元素的单调关系来解决的问题。
实现策略

单调栈的实现通常遵循以下步骤:

  1. 初始化空栈: 创建一个空栈来存储序列中的元素索引。
  2. 遍历元素: 从头开始或从尾开始遍历序列中的元素。
  3. 维护栈的单调性:
    • 如果当前元素符合栈的单调性,则将其索引压入栈中。
    • 如果当前元素破坏了栈的单调性,则连续弹出栈顶元素,直到栈变为单调。在每次弹出时,根据问题需求处理弹出的元素。
  4. 记录结果: 在处理每个元素时,根据问题需求更新结果。
算法流程
  1. 初始化一个空栈和答案数组,答案数组中的所有元素初始为0
  2. 从后向前遍历温度数组。
    • 对于每个元素,不断弹出栈顶,直到栈顶元素对应的温度大于当前温度。
    • 如果栈不为空,栈顶元素与当前元素的差值即为答案数组中当前位置的值。
    • 将当前元素的索引压入栈中。
  3. 返回答案数组。

代码实现

Python 实现

class Solution:
    def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
        stk = []
        n = len(temperatures)
        ans = [0] * n
        for i in range(n - 1, -1, -1):        
            while stk and temperatures[stk[-1]] <= temperatures[i]:
                stk.pop()
            if stk:
                j = stk[-1]
                ans[i] = j - i
            stk.append(i)
        return ans

C++ 实现

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        int n = temperatures.size();
        stack<int> stk;
        vector<int> ans(n, 0);
        for (int i = n - 1; i >= 0; --i) {
            while (!stk.empty() && temperatures[stk.top()] <= temperatures[i]) {
                stk.pop();
            }
            if (!stk.empty()) {
                int j = stk.top();
                ans[i] = j - i;
            }
            stk.push(i);
        }
        return ans;
    }
};

Java 实现

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        Stack<Integer> stk = new Stack<>();
        int n = temperatures.length;
        int[] ans = new int[n];
        for (int j = n - 1

; j >= 0; --j) {
            while (!stk.empty() && temperatures[stk.peek()] <= temperatures[j]) {
                stk.pop();
            }
            if (!stk.empty()) {
                int i = stk.peek();
                ans[j] = i - j;
            }
            stk.push(j);
        }
        return ans;
    }
}

结语

通过上述解析,我们可以看到单调栈在解决特定类型问题时的高效性和实用性。希望本文的解析对您有所帮助。如有疑问或建议,欢迎留言交流。

  • 17
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值