模版题-单调栈专题-每日温度

管理员
**单调栈:** 1. 保证栈内元素的单调性( '从栈底到栈顶' 或递增 或递减 ) 2. 保证单调性的基准是什么 栈内放入的元素是什么( 本题利用温度保持单调性 将下标存入栈中 ) ```python class Solution: # 给定一个整数数组temperatures,表示每天的温度,返回一个数组answer, # 其中answer[i]是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。 # 示例: # 输入: temperatures = [73,74,75,71,69,72,76,73] # 输出: [1,1,4,2,1,1,0,0] def dailyTemperatures(self, temperatures: List[int]) -> List[int]: # 单调栈: # 1. 保证栈内元素的单调性( '从栈底到栈顶' 或递增 或递减 ) # 2. 保证单调性的基准是什么 栈内放入的元素是什么( 本题利用温度保持单调性 将下标存入栈中 ) # 下一个更高温度出现在几天后 # 保证栈中温度从'栈底到栈顶'是递增的 为了方便确定几天后 栈顶存储下标 n = len( temperatures ) st = [] ans = [ 0 for _ in range( n ) ] for i, v in enumerate( temperatures ): while st and v > temperatures[ st[ -1 ] ]: # 保证栈内没有比栈顶温度小的元素 idx = st.pop() ans[ idx ] = i - idx st.append( i ) return ans ``` ## 单调栈详解 ``` 单调栈能够解决的问题 单调栈(Monotonic Stack)是一种栈内元素保持单调递增或单调递减的栈结构。 它在遍历元素时,能够高效地找到每个元素"左/右侧第一个比它大/小"的元素。 时间复杂度通常为 O(n),常用于替代暴力双层循环。 ═══════════════════════════════════════════ 一、核心能解决的问题 ═══════════════════════════════════════════ 1. 下一个更大元素 / 下一个更小元素 - 找每个元素右侧第一个比它大的元素(Next Greater Element) - 找每个元素右侧第一个比它小的元素(Next Smaller Element) - 同理也可以找左侧 2. 上一个更大元素 / 上一个更小元素 - 找每个元素左侧第一个比它大的元素(Previous Greater Element) - 找每个元素左侧第一个比它小的元素(Previous Smaller Element) 3. 区间最值相关 - 以某个元素为最值的最大区间范围(如柱状图中最大矩形) - 每个元素作为最值的影响范围 4. 括号匹配与表达式求值 - 验证括号是否有效 - 表达式的解析与计算 ═══════════════════════════════════════════ 二、经典题目分类 ═══════════════════════════════════════════ 【类型 A:下一个/上一个 更大/更小 元素】 LeetCode 496 - 下一个更大元素 I (模板题) LeetCode 503 - 下一个更大元素 II (循环数组) LeetCode 556 - 下一个更大元素 III (下一个排列) LeetCode 739 - 每日温度 (找右侧第一个更大的距离) LeetCode 901 - 股票价格跨度 (左侧第一个更大的距离) 【类型 B:柱状图/矩形面积】 LeetCode 84 - 柱状图中最大的矩形 (最经典,左右第一个更小元素) LeetCode 85 - 最大矩形 (二维扩展) LeetCode 42 - 接雨水 (两侧最大值,单调栈/双指针) LeetCode 1856 - 子数组最小乘积的最大值 (以某元素为最小值的区间) 【类型 C:字典序/排列】 LeetCode 316 - 去除重复字母 (单调栈保证字典序) LeetCode 1081 - 不同字符的最小子序列 (同上) LeetCode 402 - 移掉 K 位数字 (单调栈找最小数字) LeetCode 321 - 拼接最大数 (两个序列单调栈合并) 【类型 D:表达式与括号】 LeetCode 20 - 有效的括号 LeetCode 32 - 最长有效括号 LeetCode 150 - 逆波兰表达式求值 LeetCode 224 - 基本计算器 LeetCode 227 - 基本计算器 II LeetCode 772 - 基本计算器 III 【类型 E:其他进阶】 LeetCode 907 - 子数组的最小值之和 LeetCode 2104 - 子数组范围和 LeetCode 2281 - 巫师的总力量和 LeetCode 2289 - 使数组按非递减顺序排列的步骤数 ═══════════════════════════════════════════ 三、单调栈的基本模板 ═══════════════════════════════════════════ 1. 找右侧第一个更大的元素(递增栈) stack = [] for i in range(n): while stack and nums[stack[-1]] < nums[i]: idx = stack.pop() result[idx] = nums[i] # 或 i - idx stack.append(i) 2. 找右侧第一个更小的元素(递减栈) stack = [] for i in range(n): while stack and nums[stack[-1]] > nums[i]: idx = stack.pop() result[idx] = nums[i] stack.append(i) 3. 循环数组版本 遍历两遍,下标取模即可 for i in range(2 * n): while stack and nums[stack[-1]] < nums[i % n]: ... ═══════════════════════════════════════════ 四、单调栈的核心思想 ═══════════════════════════════════════════ - 当前元素破坏了栈的单调性时,就弹出栈顶, 此时: · 弹出的元素 = 找到了它要的结果 · 当前元素 = 结果的值 - 遍历完后栈中剩余的元素,就是没有找到结果的元素。 - 单调栈本质上是用空间换时间, 将"对每个元素找左/右第一个更大/更小"从 O(n²) 降到 O(n)。 ```
评论 0

发表评论 取消回复

Shift+Enter 换行  ·  Enter 发送
还没有评论,来发表第一条吧