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
相关推荐
见合八方6 分钟前
【滤波器】热调谐FP滤波器
人工智能·算法
古城小栈7 分钟前
cargo-pprof:Rust性能调优
人工智能·算法·rust
x_xbx17 分钟前
LeetCode:543. 二叉树的直径
算法·leetcode·职场和发展
QiLinkOS18 分钟前
QiLink 技术委员会选举实施细则
c语言·数据结构·c++·单片机·嵌入式硬件·算法·开源
我材不敲代码22 分钟前
Python基础: 函数超全详解:定义、参数、返回值、作用域与递归
开发语言·python·算法
无忧.芙桃24 分钟前
数据结构之顺序表的实现
数据结构
罗超驿28 分钟前
11.LeetCode 1004. 最大连续1的个数 III | 滑动窗口解法详解(Java)
java·算法·leetcode
我叫张小白。32 分钟前
Redis的缓存雪崩、击穿、穿透和解决方案
数据结构·redis·fastapi·缓存穿透·缓存击穿·雪崩·热点key问题
QiLinkOS32 分钟前
发明人与专利价值共生逻辑
c语言·数据结构·c++·人工智能·单片机·嵌入式硬件·算法
计算机安禾43 分钟前
【算法分析与设计】第21篇:回溯法的状态空间树与剪枝函数设计
大数据·人工智能·算法·机器学习·数据挖掘·剪枝