0
点赞
收藏
分享

微信扫一扫

【算法笔记】栈与队列

大柚子top 2022-01-27 阅读 88

基础知识

  1. 栈提供push 和 pop 等等接口,所有元素必须符合先进后出规则,所以栈不提供走访功能,也不提供迭代器(iterator)。STL中栈往往不被归类为容器,而被归类为container adapter(容器适配器)。
  2. 栈的底层实现可以是vector,deque,list , 主要就是数组和链表的底层实现。
std::stack<int, std::vector<int> > third;  // 使用vector为底层容器的栈

队列

队列是先进先出的数据结构,同样不允许有遍历行为,不提供迭代器,也可以指定list 为起底层实现

std::queue<int, std::list<int>> third; // 定义以list为底层容器的队列

队列也不被归类为容器,而被归类为container adapter( 容器适配器)。

例题

232. 用栈实现队列

class MyQueue {
public:
    stack<int> stin;
    stack<int> stout;
    MyQueue() {

    }
    
    void push(int x) {
        stin.push(x);
    }
    
    int pop() {
        int re;
        if(stout.empty()){
            while(!stin.empty()){
                re=stin.top();
                stin.pop();
                stout.push(re);
            }

        }
        re=stout.top();
        stout.pop();
        return re;
    }
    
    int peek() {
        int re;
        if(stout.empty()){
            while(!stin.empty()){
                re=stin.top();
                stin.pop();
                stout.push(re);
            }

        }
        re=stout.top();
        return re;
    }
    
    bool empty() {
        if(stin.empty() && stout.empty()){
            return true;
        }
        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. 用队列实现栈

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

    }
    
    void push(int x) {
        q1.push(x);
        

    }
    
    int pop() {
        int size=q1.size();
        for(int i=0;i<size-1;i++){//弹出q1
            q2.push(q1.front());
            q1.pop();
        }
        for(int i=0;i<size-1;i++){
            q1.push(q2.front());
            q2.pop();
        }
        int x=q1.front();
        q1.pop();
        return x;
    }
    
    int top() {
        int x=q1.back();

        return x;
    }
    
    bool empty() {
        if(q1.empty()){
            return true;
        }
        else{
            return false;
        }
    }
};

/**
 * 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();
 */
class MyStack {
public:
    queue<int> q;
    MyStack() {

    }
    
    void push(int x) {
        q.push(x);
    }
    
    int pop() {
        int size=q.size();
        int x;
        for(int i=0;i<size-1;i++){
            x=q.front();
            q.pop();
            q.push(x);
        }
        x=q.front();//此时队首元素就是栈顶元素
        q.pop();
        return x;
    }
    
    int top() {
        int x=q.back();
        return x;
    }
    
    bool empty() {
        if(q.empty()){
            return true;
        }
        return false;
    }
};

/**
 * 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(int i=0;i<s.size();i++){
            if(s[i]=='(' || s[i]=='[' || s[i]=='{'){
                st.push(s[i]);
            }
            else{
                if(!st.empty() && s[i]==')' && st.top()=='('){//!st.empty()是避免出现")"这种情况
                    st.pop();

                }
                else if(!st.empty() && s[i]==']' && st.top()=='['){
                    st.pop();
                }
                else if(!st.empty() && s[i]=='}' && st.top()=='{'){
                    st.pop();
                }
                else{
                    return false;
                }

            }
        }
        if(st.size()==0){
            return true;
        }
        return false;
    }
};

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

class Solution {
public:
    string removeDuplicates(string s) {
        stack<int> q;
        string re;
        for(int i=0;i<s.size();i++){
            if(q.empty()){
                q.push(s[i]);
            }
            else if(!q.empty() && s[i]==q.top()){
                q.pop();
            }
            else {
                q.push(s[i]);
            }
        }
        while(!q.empty()){
            re+=q.top();
            q.pop();
        }
        reverse(re.begin(),re.end());
        return re;
    }
};
class Solution {
public:
    string removeDuplicates(string s) {
        string re;
        for(char a:s){
            if(re.empty() || re.back()!=a){
                re.push_back(a);
            }
            else{
                re.pop_back();
            }
        }
        return re;
    }
};
class Solution {
public:
    string removeDuplicates(string s) {
        int l=0;
        int r=0;
        for(;r<s.size();r++){
            s[l]=s[r];
            if(l>0 && s[l]==s[l-1]){
                l--;
            }
            else{
                l++;
            }
        }
        s.resize(l);
        return s;
    }
};

150. 逆波兰表达式求值
逆波兰式

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> st;
        for(int i=0;i<tokens.size();i++){
            if(st.empty() || (tokens[i]!="+" && tokens[i]!="-" && tokens[i]!="*" && tokens[i]!="/")){//当前字符串为数字
                st.push(stoi(tokens[i]));
                
            }
            else{
                int r=st.top();
                st.pop();
                int l=st.top();
                st.pop();
                int re;
                if(tokens[i]=="+"){
                    re=l+r;
                }
                else if(tokens[i]=="-"){
                    re=l-r;
                }
                 else if(tokens[i]=="*"){
                    re=l*r;
                }
                else{
                    re=l/r;
                }
                
                st.push(re);
            }
           
        }
         return st.top();
    }
};

239. 滑动窗口最大值

class Solution {
public:
    class Myqueue{
public:
    deque<int> q;
        void push(int v){//维持从大到小的队列
            while(!q.empty() && v>q.back()){
                q.pop_back();//队尾出队
            }
            q.push_back(v);//队尾入队
        }
        void pop(int v){
            if(!q.empty() && v==q.front()){
                q.pop_front();//队首出队
            }

        }
        int front(){
            return q.front();
        }
    };
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        Myqueue q;
        vector<int> result;
        int l=0;
        int r=k;
        for(int i=0;i<r;i++){//先将前k个数入队
            q.push(nums[i]);
            
        }
        
        result.push_back(q.front());//第一个窗口的最大值
        if(nums[l]==q.front()){//第一个窗口向前移动时判断是否删除队首元素
            q.pop(nums[l]);
        }
        for(l=1;r<nums.size();r++, l++){
                 
            q.push(nums[r]);//窗口右端入队
            result.push_back(q.front());//记录当前窗口的最大值
            if(nums[l]==q.front()){//要删除元素等于队首元素,队首元素出队
            q.pop(nums[l]);
            }     
        }
        return result;
    }
};

347. 前 K 个高频元素

class Solution {
public:
    class myComparison{
        public:
        bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs){
        return lhs.second>rhs.second;//小顶堆
        }
    };
    
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int ,int>umap;
        for(int i=0;i<nums.size();i++){
            umap[nums[i]]++;
        }

        priority_queue<pair<int,int>,vector<pair<int,int> >,myComparison >pri_que;
        for(unordered_map<int,int>::iterator it=umap.begin();it!=umap.end();it++){
            pri_que.push(*it);
            if(pri_que.size()>k){
                pri_que.pop();
            }
        }
        vector<int> result(k);
        for(int i=k-1;i>=0;i--){
            result[i]=pri_que.top().first;
            pri_que.pop();
        }
        return result;
    }
};

总结

  1. 由于栈结构的特殊性,非常适合做对称匹配类的题目。
  2. 要找窗口的最值考虑单调队列。
  3. 一般我们说 top K 问题或者部分排序,就可以用大顶堆或小顶堆来实现,最大的 K 个:小顶堆。最小的 K 个:大顶堆
举报

相关推荐

0 条评论