- 单调栈实际上还是栈,只不过让栈内的元素保持有序(单调递增或单调递减)
我们拿一个问题来理解一下:
- 给你一个数组,返回一个等长的数组,对应索引存储下一个更大的元素,如果没有更大的元素,就存 -1.
- 输入[2,1,2,4,3] ,输出[4,2,4,-1,-1]
- 解释: 第一个2后面比2大的数是4,1后面比1大的数是2,第二个2后面比2大的数是4,4后面没有比4大的数,填 -1 ;3后面没有比3大的数,填 -1
这个题,我们也可以通过暴力求解,对于每一个元素后面进行扫描,找到第一个更大的元素即可,但是暴力解法时间复杂度为O(n^2)
我们可以这样抽象思考一下
如何在栈中保持单调递增或者单调递减?
vector<int> nextGreaterElement(vector<int>& nums) {
vector<int> ans(nums.size());
stack<int> s;
for (int i = nums.size() - 1; i >= 0; i--) {
while (!s.empty() && s.top() <= nums[i]) {
s.pop();
}
//让栈中单调从后往前
ans[i] = s.empty() ? -1 : s.top();
//判断从后往前进行测试
s.push(nums[i]);
}
return ans;
}
单调栈的时间复杂度为O(n),所有元素只会进栈一遍
单调栈一般分为单调递增和单调递减两种:
单调递增:
- 当要插入的元素 a比栈顶元素大的时候,将栈中元素出栈,直到栈为空或者比栈顶元素小
单调递减:
- 当插入的元素 b 比栈顶元素小的时候,将栈中元素出栈,直到栈为空,或者比栈顶元素大