leetcode_栈与队列

本文介绍了如何使用栈和队列来解决编程问题,如用栈实现队列,用队列实现栈,检查括号的有效性,删除字符串重复项,求解逆波兰表达式,找到滑动窗口的最大值以及找出数组中的前k个高频元素。这些例子展示了栈和队列数据结构在算法设计中的灵活性。
摘要由CSDN通过智能技术生成

栈与队列理论基础

栈与队列理论基础

232.用栈实现队列

力扣题目链接

class MyQueue {
public:
    stack<int> stIn;
    stack<int> stOut;
    MyQueue() {

    }
    
    void push(int x) {
        stIn.push(x);
    }
    
    int pop() {
        if(stOut.empty()){
            while(!stIn.empty()){
                stOut.push(stIn.top());
                stIn.pop();
            }
        }
        int res = stOut.top();
        stOut.pop();
        return res;
    }
    
    int peek() {
        if(stOut.empty()){
            while(!stIn.empty()){
                stOut.push(stIn.top());
                stIn.pop();
            }
        }
        int res = stOut.top();
        return res;
    }
    
    bool empty() {
        if(stOut.empty() && stIn.empty()){
            return true;
        }
        else{
            return false;
        }

    }
};

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue* obj = new MyQueue();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->empty();
 */

225.用队列实现栈

力扣题目链接

C++deque的基本操作:

总体思路:deq2当deq1的备份使用,每次pop(),或者top(),都把deq1中的元素都移到deq2中,只给deq1留下一个元素,pop()或者top()结束后再把deq2中的元素移回来。

class MyStack {
public:
    deque<int> deq1;
    deque<int> deq2;
    MyStack() {

    }
    
    void push(int x) {
        deq1.push_back(x);
    }
    
    int pop() {
        if(!deq1.empty()){
            while(deq1.size()>1){
                deq2.push_back(deq1.front());
                deq1.pop_front();
            }
        }
        int res = deq1.front();
        deq1.pop_front();
        while(!deq2.empty()){
            deq1.push_back(deq2.front());
            deq2.pop_front();
        }
        return res;
    }
    
    int top() {
        if(!deq1.empty()){
            while(deq1.size()>1){
                deq2.push_back(deq1.front());
                deq1.pop_front();
            }
        }
        int res = deq1.front();
        deq2.push_back(res);
        deq1.pop_front();
        while(!deq2.empty()){
            deq1.push_back(deq2.front());
            deq2.pop_front();
        }
        return res;
    }
    
    bool empty() {
        return deq1.empty();
    }
};

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack* obj = new MyStack();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->top();
 * bool param_4 = obj->empty();
 */

20.有效的括号

力扣题目链接

class Solution {
public:
    bool isValid(string s) {
        stack<char> st;
        for (auto str : s)
        {
            switch (str) {
                case '(':
                case '{':
                case '[':
                    if (str == '(') st.push(')');
                    else if (str == '{') st.push('}');
                    else st.push(']');
                    break;
                case ')':
                case '}':
                case ']':
                    if (st.empty()) {
                        return false;
                    }
                    if (str != st.top()) {
                        return false;
                    }
                    else {
                        st.pop();
                        break;
                    }
            }
        }
        if (st.empty()) return true;
        else return false;
    }
};

1047.删除字符串中的所有相邻重复项

力扣题目链接

class Solution {
public:
    string removeDuplicates(string s) {
        stack<char> st;
        string res;
        for(auto str:s){
            if(st.empty()){
                st.push(str);
            }
            else{
                if(str==st.top()){
                    st.pop();
                }
                else{
                    st.push(str);
                }
            }
        }
        if(st.empty()){
            return "";
        }
        else{
            while(!st.empty()){
                res+=st.top();
                st.pop();
            }
            reverse(res.begin(),res.end());
            return res;
        }
    }
};

150.逆波兰表达式求值

力扣题目链接

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<long long> st;
        for(int i =0;i<tokens.size();i++){
            if(tokens[i]=="+"||tokens[i]=="-"||tokens[i]=="*"||tokens[i]=="/"){
                long long num1 = st.top();
                st.pop();
                long long num2 = st.top();
                st.pop();
                if(tokens[i]=="+") st.push(num2+num1);
                else if(tokens[i]=="-") st.push(num2-num1);
                else if(tokens[i]=="*") st.push(num2*num1);
                else st.push(num2/num1);
            }
            else{
                st.push(stoll(tokens[i]));
            }
        }
        int res = st.top();
        st.pop();
        return res;
    }
};

239.滑动窗口最大值

力扣题目链接
单调队列≠对窗口里的元素进行实时排序

单调队列设计思想:

  1. pop(val):如果窗口元素val的值等于队列出口的元素的值,则弹出队列出口的元素的值,否则不进行任何操作
  2. push(val):如果窗口元素val的值大于队列入口元素的值,则弹出队列入口的元素的值,一直到窗口元素的值小于等于队列入口的元素。
  3. front():返回队列出口的元素的值。
class Solution {
private:
    class Myqueue {
    public:
        deque<int> deq;
        void pop(int val) {
            if (!deq.empty() && deq.front() == val) {
                deq.pop_front();
            }
        }
        void push(int val) {
            while (!deq.empty() && val > deq.back()) {
                deq.pop_back();
            }
            deq.push_back(val);  
        }
        int front() {
            return deq.front();
        }
    };
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        Myqueue mq;
        vector<int> res;
        for (int i = 0; i < k; i++) {
            mq.push(nums[i]);
        }
        res.push_back(mq.front());
        for (int i = k; i < nums.size(); i++)
        {
            mq.pop(nums[i-k]);
            mq.push(nums[i]);
            res.push_back(mq.front());
        }
        return res;
    }
};

347.前k个高频元素

力扣题目链接
C++priority_queue的使用方法
优先级队列:priority_queue容器适配器模拟的也是队列这种存储结构,即使用此容器适配器存储元素只能从一端进,从另一端出,且每次只能访问队列中的队头元素,和队尾元素。但优先级队列遵循的原则不是先入先出,而是先入优先级大的出。

  1. 大顶堆:最大的元素在堆顶
    • 大顶堆的排序规则:bool operator()(const T &_lhs,const T &_rhs) const{ return _lhs<_rhs;}
    • 把大元素放到右面也就是堆顶,也就是队列要pop的地方。
  2. 小顶堆:最小的元素在堆顶
    • 小顶堆的排序规则:bool operator()(const T &_lhs,const T &_rhs) const{ return _lhs>_rhs;}
    • 把小元素放到右面也就是堆顶,也就是队列要pop的地方。

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    class cmp {
    public:
        bool operator()(pair<int, int> lhs, pair<int, int>rhs) {
            return lhs.second > rhs.second;
        }
    };
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> umap;
        vector<int> res;
        for (int i = 0; i < nums.size(); i++) {
            umap[nums[i]]++;
        }
        priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> prq;
        for (auto iter = umap.begin(); iter != umap.end(); iter++)
        {
            int a = iter->first;
            int b = iter->second;
            prq.push({a,b});   // prq.push(pair<int,int>(a,b))  or prq.push(*iter)
            if (prq.size() > k)
            {
                prq.pop();
            }
        }
        while (!prq.empty()) {
            auto ans = prq.top();
            res.push_back(ans.first);
            prq.pop();
        }
        return res;
    }
};

栈与队列总结

栈与队列总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值