火龙信奥
  • 首页
  • 课程
  • 题库
  • 打卡
    • 代码对战
    • 快速对战
  • 题单
  • 团队
  • 荣誉墙
  • 商城
  • 登录 / 注册

高中信息技术-单调栈和单调队列

作者: 作者的头像   huolong , 时间:2025-06-21 19:07:41 , 所有人可见, 阅读  2

下面是两个函数的完整代码,包含详细注释、函数含义和物理意义解释。这两个函数分别用于:

✅ 1. dailyTemperatures(temperatures) 功能:

计算每一天之后需要等待多少天才能遇到一个更温暖的天气(即温度更高的日子)。

物理意义:

这是一个经典的 “每日温度”问题,模拟了现实生活中人们关心“明天是否更热”的问题。它也可以被看作是一个 “下一个更大元素” 的变种问题。

实现方式:

使用了一个 栈(stack) 来保存温度的索引,通过从后往前遍历数组的方式,维护一个单调递增的栈结构。

✅ 2. sliding_window_max(nums, k=3) 功能:

找出每个大小为 k 的滑动窗口中的最大值。

物理意义:

这是数据流中常见的处理任务,例如监控系统每5分钟取一次CPU占用率的最大值、股票价格波动分析等场景。它是典型的 滑动窗口最大值问题。

实现方式:

使用了一个 单调队列(Monotonic Queue) 来维护当前窗口中可能成为最大值的元素索引。这个队列始终保持递减顺序。

def dailyTemperatures(temperatures):
    """
    计算每天之后需要等待多少天才会有更高温度。

    参数:
        temperatures (List[int]): 温度列表,表示每天的温度

    返回:
        List[int]: 每个位置i的答案表示在第i天之后要等几天才能遇到更高温度;
                   如果之后没有更高温度,则对应结果为0。

    物理意义:
        解决“下一个更高温度”的问题,常用于天气预报或类似序列分析。
        使用栈维护“尚未找到更高温度”的日期索引,实现O(n)时间复杂度。
    """
    n = len(temperatures)
    sk = []          # 栈,保存的是索引
    ans = [0] * n    # 答案数组

    # 从后往前遍历
    for i in range(n - 1, -1, -1):
        # 如果当前温度 >= 栈顶温度,弹出栈顶(说明这些天不会是答案)
        while sk and temperatures[i] >= temperatures[sk[-1]]:
            sk.pop()

        if sk:
            # 栈顶是第一个比当前温度高的日子
            ans[i] = sk[-1] - i
        else:
            ans[i] = 0

        sk.append(i)  # 把当前索引压入栈

    return ans


# 示例测试
temps = [73, 74, 75, 71, 69, 72, 76, 73]
print("每日温度问题结果:", dailyTemperatures(temps))
# 输出: [1, 1, 4, 2, 1, 1, 0, 0]


def sliding_window_max(nums, k=3):
    """
    找出每个大小为k的滑动窗口中的最大值。

    参数:
        nums (List[int]): 整数数组
        k (int): 滑动窗口大小,默认为3

    返回:
        List[int]: 每个窗口内的最大值组成的列表

    物理意义:
        常见于实时数据分析、信号处理、金融数据统计等领域。
        使用“单调队列”思想优化查找过程,避免暴力枚举,提升效率到O(n)。

    实现思路:
        - 维护一个双端队列 dq,保存的是元素索引,且这些索引对应的值保持递减顺序。
        - 队首始终是当前窗口最大值的索引。
        - 当窗口滑动时,移除过期索引和不合适的候选值。
    """
    if not nums or k <= 0:
        return []

    n = len(nums)
    result = []
    dq = []  # 用普通列表模拟双端队列,保存索引

    for i in range(n):
        # 移除超出窗口范围的索引(只检查队首)
        while dq and dq[0] < i - k + 1:
            dq.pop(0)  # 模拟 popleft()

        # 移除比当前元素小的所有元素(保持单调递减)
        while dq and nums[dq[-1]] < nums[i]:
            dq.pop()

        # 将当前元素索引加入队列
        dq.append(i)

        # 当窗口长度达到k时,记录当前最大值
        if i >= k - 1:
            result.append(nums[dq[0]])

    return result


# 示例测试
a = [1, 3, -1, 5, 3, 6, 7]
k = 3
print("滑动窗口最大值问题结果:", sliding_window_max(a, k))
# 输出: [3, 5, 5, 6, 7]


—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com

©2026加盟我们 | 关于我们 | ACM课程 | 常见问题 | 成果墙 | 评测记录 | 浙ICP备2021013995号
在线画图 | OI WIki | 打字练习
火龙信奥
请输入登录信息


请完成安全验证
验证码底图 滑块
向右拖动滑块完成验证
请输入用户名 / 绑定的手机号码



请输入注册信息(手机号验证码注册)





验证码5分钟有效,60秒内不可重复获取,每日最多3次

微信登录

微信登录二维码

正在生成二维码...

账号已过期,请续期。
去续期

绑定手机号

📱

为了更好地保护您的账号安全,享受完整的平台服务

请您尽快绑定手机号码