单调栈是什么?
找出数组中每个数右边第一个比它大的元素
思路
单调递增栈
我们用栈来保存未找到右边第一个比它大的元素的索引(保存索引是因为后面需要靠索引来给新数组赋值)
如果要找出数组中每个数右边第一个比它小的元素,只要把单调栈变成递减栈就好
#include<iostream>
#include<stack>
#include<vector>
using namespace std;
vector<int> RightFirstGreater(vector<int>nums) {
vector<int>res(nums.size());
stack<int>s;//保存的是还没找到结果的元素索引
int index = 0;
while(index < nums.size()) {
if(!s.empty() && nums[index] > nums[s.top()]) {
res[s.top()] = nums[index];//有结果了
s.pop();
}
else {
s.push(index);
++index;
}
}
//还有没有结果的,全部赋值-1
while(!s.empty()){
res[s.top()] = -1;
s.pop();
}
return res;
}
int main() {
auto res = RightFirstGreater(vector<int>{8, 2, 5, 4, 3, 9, 7, 2, 5});
for(int i:res)
cout<<i<<" ";
cout<<endl;
}
// 9 5 9 9 9 -1 -1 5 -1
找出数组中每个数左边第一个比它大的元素
和上面的类似,只是从右边开始遍历
#include<iostream>
#include<stack>
#include<vector>
using namespace std;
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
}
};
vector<int> RightFirstGreater(vector<int>nums) {
vector<int>res(nums.size());
stack<int>s;
int index = nums.size() - 1;
while(index >= 0) {
if(!s.empty() && nums[index] > nums[s.top()]) {
res[s.top()] = nums[index];
s.pop();
}
else {
s.push(index);
--index;
}
}
while(!s.empty()){
res[s.top()] = -1;
s.pop();
}
return res;
}
int main() {
auto res = RightFirstGreater(vector<int>{8, 2, 5, 4, 3, 9, 7, 2, 5});
for(int i:res)
cout << i << " ";
cout << endl;
}
// -1 8 8 5 4 -1 9 7 7
239.滑动窗口的最大值
思路:单调队列
class Solution {
deque<int>d;
vector<int>res;
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
int sz = nums.size();
for (int i = 0; i < sz; i++) {
if (i < k - 1)//前k-1个元素入队
push(nums[i]);
else {
push(nums[i]);
res.push_back(max_num());
pop(nums[i - k + 1]);
}
}
return res;
}
void push(int i) {//保证队列里的值是单调减(头到尾)
while (!d.empty() && d.back() < i) {
d.pop_back();
}
d.push_back(i);
}
int max_num() {//返回当前滑动窗口最大的值
return d.front();
}
//新的窗口是否已经不再包含原来那个最大的数,如果不再包含,我们就把旧的数从双端队列的头删除
void pop(int n) {
if (!d.empty() && d.front() == n)
d.pop_front();
}
};
复杂度
时间O(N)
空间O(k)