代码随想录刷题记录——栈与队列篇

栈与队列理论基础

  •  栈stack:先进后厨
  • 队列queue:先进先出
  • STL(C++标准库)
  • STL 栈和队列属于容器适配器(container adapter)
  • 优先队列priority_queue:
    • 默认大根堆,如果是pair<a,b>,默认比较a大小
    • 如果需要比较b大小,且小根堆,可以如下实现

232.用栈实现队列

题目链接

  •  pop操作时,当out栈为空时,需要将in栈全部取出并放入out
复制代码
#include<bits/stdc++.h>
using namespace std;

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

    }
    
    void push(int x) {
        stIn.push(x);
    }
    
    int pop() {
        //只有Out栈为空时,需要把In栈全部放到Out栈
        if(stOut.empty()){
            while(!stIn.empty()){
            stOut.push(stIn.top());
            stIn.pop();
            }
        }       
        int a = stOut.top();
        stOut.pop();
        return a;
    }
    
    int peek() {
        int a = this->pop();
        stOut.push(a);
        return a;
    }
    
    bool empty() {
        return stIn.empty()&&stOut.empty();
    }
};
复制代码

 

 

225. 用队列实现栈

题目链接

  • pop操作时,把除最后一个元素外所有元素取出队列再放进,此时再取出下一个元素即模拟可栈后进先出。
复制代码
#include<bits/stdc++.h>
using namespace std;

class MyStack {
public:
    queue<int> que;
    MyStack() {

    }
    
    void push(int x) {
        que.push(x);
    }
    
    int pop() {
        int size = que.size();
        while(size>1){
            que.push(que.front());
            que.pop();
            size--;
        }
        int ans = que.front();
        que.pop();
        return ans;
    }
    
    int top() {
        return que.back();
    }
    
    bool empty() {
        return que.empty();
    }
};
复制代码

 

 

20. 有效的括号

题目链接

复制代码
#include<bits/stdc++.h>
using namespace std;

class Solution {
public:
    bool isValid(string s) {
        stack<char> st;
        for(int i=0;i<s.size();i++){
            if(s[i]=='(')   st.push(')');
            else if(s[i]=='{')  st.push('}');
            else if(s[i]=='[')  st.push(']');
            else if(st.empty()||s[i]!=st.top()) return false;
            else    st.pop();
        } 
        return st.empty();
    }
};
复制代码

 

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

题目链接

复制代码
#include<bits/stdc++.h>
using namespace std;

class Solution {
public:
    string removeDuplicates(string s) {
        stack<char> st;
        for(int i=0;i<s.size();i++){
            if(st.empty()||st.top()!=s[i])  st.push(s[i]);
            else    st.pop();
        }
        string ans = "";
        while(!st.empty()){
            ans += st.top();
            st.pop();
        }
        reverse(ans.begin(),ans.end());
        return ans;
    }
};
复制代码
  • C++中,std::string类提供类似入栈、出栈接口
复制代码
class Solution {
public:
    string removeDuplicates(string s) {
        string stk;
        for (char ch : s) {
            if (!stk.empty() && stk.back() == ch) {
                stk.pop_back();
            } else {
                stk.push_back(ch);
            }
        }
        return stk;
    }
};
复制代码

 

 

 

150. 逆波兰表达式求值

题目链接

复制代码
#include<bits/stdc++.h>
using namespace std;

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> st;
        for(string token: tokens){
            if(token!="+"&&token!="-"&&token!="*"&&token!="/"){
                int t = stoi(token);//stoi函数,string to int 缩写
                st.push(t);
            }
            else{
                int num1 = st.top();
                st.pop();
                int num2 = st.top();
                st.pop();
                if(token=="+")  st.push(num2+num1);
                if(token=="-")  st.push(num2-num1);
                if(token=="*")  st.push(num2*num1);
                if(token=="/")  st.push(num2/num1);
            }
        }
        int ans = st.top();
        st.pop();
        return ans;
    }
};
复制代码

 

 

239. 滑动窗口最大值

题目链接

  • 优先队列priority_queue
  • 需要存下标,判断是否在窗口内
复制代码
#include<bits/stdc++.h>
using namespace std;

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        priority_queue<pair<int, int>> que;//pair<nums[i], i>
        for(int i=0;i<k;i++){
            que.emplace(nums[i], i);
        }
        vector<int> ans = {que.top().first};
        //开始滑动
        for(int i=k;i<nums.size();i++){
            que.emplace(nums[i], i);
            //当优先队列队首值(最大值)index没在窗口范围内,出队列,保证最大值索引在窗口内
            while(que.top().second<=i-k){
                que.pop();
            }
            ans.push_back(que.top().first);
        }
        return ans;
    }
};
复制代码

 

 

  • 单调队列
复制代码
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        int n = nums.size();
        deque<int> q;
        for (int i = 0; i < k; ++i) {
            while (!q.empty() && nums[i] >= nums[q.back()]) {
                q.pop_back();
            }
            q.push_back(i);
        }

        vector<int> ans = {nums[q.front()]};
        for (int i = k; i < n; ++i) {
            while (!q.empty() && nums[i] >= nums[q.back()]) {
                q.pop_back();
            }
            q.push_back(i);
            while (q.front() <= i - k) {
                q.pop_front();
            }
            ans.push_back(nums[q.front()]);
        }
        return ans;
    }
};
复制代码

 

 

347.前 K 个高频元素

题目链接

  • 使用优先队列定义小根堆并自定义比较方式时需注意:
    • priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> minHeap(cmp);
    • static bool cmp(pair<int, int> &m, pair<int, int> &n)
    • 即decltype(&cmp)里的‘&’不能少,且cmp函数需要是static静态函数,否则decltype推断时报错
复制代码
#include<bits/stdc++.h>
using namespace std;

class Solution {
public:
    static bool cmp(pair<int, int> &m, pair<int, int> &n) {
        return m.second > n.second;
    }

    vector<int> topKFrequent(vector<int>& nums, int k) {
        priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> minHeap(cmp);//小根堆
        unordered_map<int, int> map;
        for(int i=0;i<nums.size();i++){
            map[nums[i]]++;
        }
        for(auto it: map){
            if(minHeap.size()==k){
                if(minHeap.top().second<it.second){
                    minHeap.pop();
                    minHeap.emplace(it.first, it.second);
                }
            }
            else{
                minHeap.emplace(it.first, it.second);
            }
        }
        vector<int> ans;
        while(!minHeap.empty()){
            ans.push_back(minHeap.top().first);
            minHeap.pop();
        }
        return ans;
    }
};
复制代码

 

 

栈与队列总结篇

  • 站和队列是容器适配器
  • 默认情况下栈和队列的底层容器是deque双端队列,
  • 栈的经典应用:括号匹配、逆波兰表达式
  • 队列经典应用:滑动窗口最大值(单调队列)、求前k个高频元素(优先级队列)

 

posted @   DaxiaWan  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示