单调栈详解
一、核心思想与特性
单调栈是一种特殊的栈结构,栈内元素保持单调递增或递减。其核心价值在于通过维护单调性,快速定位数组中元素的下一个更大/更小值,将暴力解法 O(n²) 优化至 O(n) 。
- 核心操作:
- 扩张:遍历数组,将新元素与栈顶比较。
- 收缩:若新元素破坏单调性,则弹出栈顶并记录解(如找到更大元素)。
- 入栈:新元素入栈,维持单调性。
- 存储索引而非值:
栈中存储元素索引而非值,便于计算距离或宽度。
二、单调栈的类型与选择
根据问题需求选择栈类型和遍历方向:
问题目标 | 栈类型 | 遍历方向 | 例子 |
---|---|---|---|
右侧第一个更大元素 | 单调递减栈 | 正向遍历 | [4,2,1] → [ -1,4,4] |
右侧第一个更小元素 | 单调递增栈 | 反向遍历 | [4,2,1] → [2,1,-1] |
左侧第一个更大元素 | 单调递减栈 | 正向遍历 | [1,2,4] → [-1,-1,-1] |
左侧第一个更小元素 | 单调递增栈 | 正向遍历 | [3,1,4] → [-1,-1,1] |
口诀:
找左侧 → 正向遍历;找右侧 → 反向遍历;
比它大 → 单调减;比它小 → 单调增。
三、基础应用:C++代码详解
1. 下一个更大元素(LeetCode 496)
问题:为 nums2
中每个元素找右侧第一个更大值,返回 nums1
子集的结果。
#include <vector>
#include <stack>
#include <unordered_map>
using namespace std;vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {stack<int> st; // 单调递减栈(存储索引)unordered_map<int, int> nextGreater; // 存储元素到下个更大值的映射// 遍历 nums2,构建映射关系for (int num : nums2) {// 当前元素比栈顶大 → 栈顶元素的下一个更大值是当前元素while (!st.empty() && num > st.top()) {nextGreater[st.top()