day41-数据结构力扣

动态规划结束,开始学单调栈

单调栈是什么?

定义

单调栈是一种特殊的栈结构,其元素按照单调递增或单调递减的顺序排列。它主要用于解决需要维护单调性的问题,例如寻找下一个更大或更小的元素。

工作原理

  • 单调递增栈:栈内元素从栈底到栈顶递增。当新元素小于栈顶元素时,栈顶元素被弹出,直到新元素可以保持单调性。

  • 单调递减栈:栈内元素从栈底到栈顶递减。当新元素大于栈顶元素时,栈顶元素被弹出,直到新元素可以保持单调性。

739. 每日温度

题目链接 739. 每日温度 - 力扣(LeetCode)

思路

这道题标准的单调栈应用 ,核心思路:用单调递减栈存储数组下标,遍历温度时,找到每个元素右侧第一个更大的元素,计算天数差。

  • 初始化

    • answer:长度和温度数组一致,默认值 0(无更高温度时直接用)

    • stack:空栈,专门存下标,不存温度值

  • 遍历逻辑

    • 循环条件:栈不为空 当前温度 > 栈顶下标对应的温度

    • 弹出栈顶元素,计算 当前下标 - 弹出下标 → 就是下一个更高温度的天数

    • 把当前下标压入栈,保持栈的单调递减特性

  • 时间 / 空间复杂度

    • 时间:O(n),每个元素入栈、出栈各一次

    • 空间:O(n),栈最多存储全部元素

提交

python 复制代码
class Solution:
    def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
        n = len(temperatures)
        answer = [0] * n  # 初始化结果数组,默认全0
        stack = []        # 单调栈:存储下标,对应温度递减
        
        for i in range(n):
            # 当前温度 > 栈顶温度,说明找到下一个更高温度
            while stack and temperatures[i] > temperatures[stack[-1]]:
                prev_idx = stack.pop()  # 弹出栈顶下标
                answer[prev_idx] = i - prev_idx  # 计算天数差
            # 当前下标入栈,维持单调递减
            stack.append(i)
        
        return answer

496.下一个更大元素 I

题目链接496. 下一个更大元素 I - 力扣(LeetCode)

题干描述的第一句话也太抽象了,直接看后面和给的示例

思路

第一步:处理 nums2,用单调栈生成「下一个更大元素表」

  • 栈保持递减

  • 遇到比栈顶大的数:

    • 栈顶弹出

    • 记录:弹出的数的下一个更大 = 当前数

  • 最后栈里剩下的数:没有更大元素 → -1

第二步:处理 nums1

  • 直接遍历每个数,去哈希表里拿结果

我刚开始想的是在nums2做一个下标和这个元素下一个更大值的映射关系

比如【1,3,4,2】映射【3,4,-1-1】,然后遍历nums1,但是这里弄下标和元素值把自己弄晕了

然后上面思路那个方法就比较清楚,直接将元素值和下一个更大元素进行映射

跳过了下标这个比较容易晕的东西

提交

python 复制代码
class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        # 1. 哈希表:key = 元素值,value = 下一个更大元素
        next_greater = {}
        stack = [] # 单调递减栈,存元素值
        
        # 遍历 nums2,求每个元素的下一个更大元素
        for num in nums2:
            # 当前数 > 栈顶,说明栈顶找到了下一个更大元素
            while stack and num > stack[-1]:
                val = stack.pop()
                next_greater[val] = num
            # 当前数入栈,维持递减
            stack.append(num)
        
            # 栈里剩下的元素,没有更大值,设为 -1
            for num in stack:
                next_greater[num] = -1
        
        # 2. 遍历 nums1,直接查表
        return [next_greater[x] for x in nums1]

503.下一个更大元素II

题目链接 503. 下一个更大元素 II - 力扣(LeetCode)

这个题和我上一个

"

我刚开始想的是在nums2做一个下标和这个元素下一个更大值的映射关系

比如【1,3,4,2】映射【3,4,-1-1】,然后遍历nums1,但是这里弄下标和元素值把自己弄晕了

"

有点像,就是第一步,还是得学会这个

但是还有一个重要的事,要循环搜索

思路

1.循环数组处理技巧

数组是环形的,最后一个元素后面接着第一个元素。

不用真的拼接数组,直接遍历 2n 次,通过 i % n 映射回原数组下标,等价于把数组复制一遍接在后面。

2.单调栈核心

维护单调递减栈,栈中存原数组下标:

遍历到当前位置,若当前元素 > 栈顶下标对应的元素,说明栈顶元素找到了下一个更大元素;

弹出栈顶下标,给结果数组赋值;

持续弹出直到栈不满足递减;

只在前 n 次遍历把下标入栈,防止重复入栈。

3.初始默认值

结果数组初始全为 -1,没找到更大元素就保持 -1。

提交

python 复制代码
class Solution:
    def nextGreaterElements(self, nums: List[int]) -> List[int]:
        n = len(nums)
        res = [-1] * n
        stack = []  # 单调栈:存放数组下标
        
        # 遍历两倍长度,模拟循环数组
        for i in range(2 * n):
            idx = i % n  # 映射回原数组下标
            # 维持单调递减,找下一个更大元素
            while stack and nums[idx] > nums[stack[-1]]:
                top_idx = stack.pop()
                res[top_idx] = nums[idx]
            # 只在第一轮存入下标,避免重复
            if i < n:
                stack.append(idx)
        return res
相关推荐
凯瑟琳.奥古斯特1 小时前
懒加载技巧优化栈增减操作(力扣3629)
开发语言·数据结构·算法
hans汉斯1 小时前
基于LSTM与扩展卡尔曼滤波的无人机机载电子磁干扰补偿研究
开发语言·人工智能·算法·目标检测·lstm·人机交互·无人机
sheeta19983 小时前
LeetCode 每日一题笔记 日期:2026.05.08 题目:3629. 素数跳跃最小次数
笔记·算法·leetcode
叼烟扛炮3 小时前
C++ 知识点08 类与对象
开发语言·c++·算法·类和对象
米粒13 小时前
力扣算法刷题 Day 63 Bellman_ford 算法
数据库·算法·leetcode
IT大白鼠10 小时前
AIGC性能的关键瓶颈:算力、数据、算法三者如何互相制约?
算法·aigc
白雪茫茫11 小时前
监督学习、半监督学习、无监督学习算法详解
python·学习·算法·ai
FengyunSky11 小时前
浅析 空间频率响应 SFR 计算
算法
树下水月11 小时前
PHP 一种改良版的雪花算法
算法·php·dreamweaver