单调栈是一种利用栈的数据结构特性解决特定类型问题的高效算法技巧,尤其是在处理数组或序列中的“最近”问题时非常有用,如“下一个更大元素”、“上升子序列长度”等。单调栈的基本思想是维护一个单调递增或递减的栈,保证栈顶元素总是满足某种单调性。以下是单调栈的一些简单应用思路及C++实现的要点:
1. 单调递增栈的应用
目标: 找到每个元素右边(或左边)第一个比它大的(小的)元素。
思路:
- 初始化一个空栈,遍历数组。
- 遇到一个元素时,如果栈顶元素满足条件(比如对于“下一个更大元素”,栈顶元素小于当前元素),则弹出栈顶元素,并记录当前元素为其对应的结果。
- 当前元素入栈。
- C++代码片段示例
vector<int> nextGreaterElement(vector<int>& nums) {
stack<int> monoStack;
vector<int> result(nums.size(), -1); // 初始化结果数组,默认无解为-1
for (int i = 0; i < nums.size(); ++i) {
while (!monoStack.empty() && nums[i] > nums[monoStack.top()]) {
result[monoStack.top()] = nums[i];
monoStack.pop();
}
monoStack.push(i);
}
return result;
}
```
2. 求最长上升子序列长度
目标: 在给定序列中找到最长的上升子序列的长度。
思路:
维护一个单调递增栈,栈中存储的是当前上升子序列可能的结尾元素的下标。
遍历数组,对于每个元素,如果它大于栈顶元素对应的值,则直接将该元素的下标入栈;否则,从栈顶开始弹出元素,直到栈为空或栈顶元素大于当前元素,然后将当前元素的下标入栈。
栈的大小即为最长上升子序列的长度。
单调栈的精髓在于利用栈的后进先出特性,快速定位并处理与当前元素相关的“历史”信息,从而达到较高的效率。