leetcode.单调栈,单调队列

单调栈是什么?

在这里插入图片描述

找出数组中每个数右边第一个比它大的元素

思路

单调递增栈
我们用栈来保存未找到右边第一个比它大的元素的索引(保存索引是因为后面需要靠索引来给新数组赋值)
如果要找出数组中每个数右边第一个比它小的元素,只要把单调栈变成递减栈就好

#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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值