• 算法总结


    一 基础知识

    1.

    均为线性表,可以由数组或链表实现 

    栈:先进后出,操作均在栈顶进行

    队列:先进先出,队尾进,队首出

    2.  STL stack & queue

    stack 常见操作:

    s.push(x):入栈 (void类型)

    s.pop(): 出栈 (void类型,只删除,不返回元素)

    s.top(): 返回栈顶元素

    s.size():返回栈元素个数

    s.empty() :判断栈是否为空

    queue 常见操作:

    q.push(x): 入队

    q.pop(): 出队 (void类型,只删除,不返回队首元素)

    q.front(): 访问返回对首元素

    q.back(): 访问返回队尾元素

    q.size():返回队列元素个数

    q.empty(): 判断队列是否为空

    3.概念理解相关题型

    3.1 Implement Stack using Queues (leetcode 225 https://leetcode.com/problems/implement-stack-using-queues/)

    思路:使用两个队列实现,其中一个队列为空,用来进行颠倒顺序和输出队尾元素。

    入栈操作: 向非空队列内入队即可

    出栈操作:将非空队列除队尾元素外的所有元素导入另一个空队列,剩余队尾元素即为待应该待出栈元素

    top()操作: 同出栈,注意只需访问返回,不需要让其出队,即仍需将其导入另一队列

    注意:两队列地位平等,均可能用作储存和转移工作

    复制代码
    class Stack {
    private:
        queue<int> q1,q2;
    public:
        // Push element x onto stack.
        void push(int x) {
            if(!q1.empty()){
                q1.push(x);
            }
            else{
                q2.push(x);
            }
        }
    
        // Removes the element on top of the stack.
        void pop() {
            if(!q1.empty()){
                while(q1.size() > 1){
                    q2.push(q1.front());
                    q1.pop();
                }
                q1.pop();
            }else{
                while(q2.size() > 1){
                    q1.push(q2.front());
                    q2.pop();
                }
                q2.pop();
            }
        }
    
        // Get the top element.
        int top() {
            if(!q1.empty()){
                while(q1.size() > 1){
                    q2.push(q1.front());
                    q1.pop();
                }
                int ans = q1.front();
                q2.push(q1.front());
                q1.pop();
                return ans;
            }else{
                while(q2.size() > 1){
                    q1.push(q2.front());
                    q2.pop();
                }
                int ans = q2.front();
                q1.push(q2.front());
                q2.pop();
                return ans;
            }
        }
    
        // Return whether the stack is empty.
        bool empty() {
            if(q1.empty() && q2.empty()){
                return true;
            }
            return false;
        }
    };
    复制代码

    3.2 Implement Queue using Stacks (leetcode 232 https://leetcode.com/problems/implement-queue-using-stacks/)

    思路:

    两个堆栈,s1负责入队,s2负责反向并出队

    每次入队直接进入s1,出队操作先将s1所有元素压入s2,则栈顶元素即为待出队元素,出队后压回s1,恢复原状。

    复制代码
    class Queue {
    private:
        stack<int> s1,s2;
    public:
        // Push element x to the back of queue.
        void push(int x) {
            s1.push(x);
        }
    
        // Removes the element from in front of queue.
        void pop(void) {
            while(!s1.empty()){
                s2.push(s1.top());  // 注意STL栈中,top只返回不出栈,pop只出栈不返回
                s1.pop();
            }
            s2.pop();
            while(!s2.empty()){
                s1.push(s2.top());
                s2.pop();
            }
        }
    
        // Get the front element.
        int peek(void) {
            while(!s1.empty()){
                s2.push(s1.top()); 
                s1.pop();
            }
            int ans = s2.top();
            while(!s2.empty()){
                s1.push(s2.top());
                s2.pop();
            }
            return ans;
        }
    
        // Return whether the queue is empty.
        bool empty(void) {
            if(s1.empty() && s2.empty()){
                return true;
            }
            return false;
        }
    };
    复制代码

    3.3 Min Stack (leetcode 155 https://leetcode.com/problems/min-stack/)

    要求:实现可以返回最小元素的栈

    思路:使用两个栈,一个栈s1正常出入,另一个储s2存最小值信息,当当前元素比s2栈顶元素小,入当前元素,否则再入一份栈顶元素

    注意:由于s1,s2元素一样多,出栈时也应一起出栈。

    复制代码
    class MinStack {
    private:
        stack<int> s1,s2;
    public:
        void push(int x) {
            s1.push(x);
            if(!s2.empty() && x > s2.top()){
                s2.push(s2.top());
            }else{
                s2.push(x);
            }
        }
    
        void pop() {
            s1.pop();
            s2.pop();
        }
    
        int top() {
            return s1.top();
        }
    
        int getMin() {
            return s2.top();
        }
    };
    复制代码

     二. 栈与队列应用 (结合数据结构教材中的应用)

    1. 典型应用场合

    典型应用栈的场合有: 逆序输出 (进制转换),递归嵌套(栈混洗,括号匹配),延迟缓冲(表达式计算),栈式计算(逆波兰表达式)

    举例如下:

    1.1 十进制数向n进制转换的栈实现

    思路:除以n取余数,以此存放在栈中,输出时由栈的特点反向输出得解

    复制代码
    void convert(stack <char>& S, int n,int base) {
        static char digit[] = 
        {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        while(n > 0){
            int remainder = (int)(n % base);
            S.push(digit[remainder]);
            n /= base;
        }
    }
    复制代码

    1.2 栈混洗(元素出入栈合法顺序判断)

    思路:使用栈模拟,对于s,如果当前要出栈元素正好在栈顶,则必须出栈;否则入栈,出现矛盾则说明不合法

    复制代码
    bool isPossible(vector<int>& in, vector<int>& out){
        stack<int> s;
        for(int i = 0,j = 0;j<out.size();j++){
            while(s.empty() || s.top!= out[j]){
                if(i > in.size()){
                    return false;
                }
                s.push(in[++]);
            }  
            s.pop();
        }
        return true;
    }
    复制代码

    补充: n个元素的合法出入栈个数为卡特兰数  (2n!)/ n! /(n+1)!

    1.3 括号匹配 (leetcode 20 https://leetcode.com/problems/valid-parentheses/)

    思路:遍历序列,遇到所有类型左括号,入栈;遇到右括号,判定栈顶元素与之是否匹配,匹配则出栈,不匹配则说明整体不匹配

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

    1.4 逆波兰表达式求解 (leetcode 150 https://leetcode.com/problems/evaluate-reverse-polish-notation/)

    思路:根据逆波兰表达式定义,建立栈

    遍历字符串,遇到数字,入栈,遇到运算符,取出栈顶两元素执行相应计算后将结果入栈

    复制代码
    class Solution {
    public:
        int evalRPN(vector<string>& tokens) {
            stack<int> s;
            for(int i = 0;i < tokens.size();i++){
                if(tokens[i] == "+" || tokens[i] == "-" || tokens[i]== "*" || tokens[i] == "/"){
                    int num1 = s.top();
                    s.pop();
                    int num2 = s.top();
                    s.pop();
                    if(tokens[i] == "+"){
                        int num = num1 + num2;
                        s.push(num);
                    }
                    if(tokens[i] == "-"){
                        int num = num2 - num1;
                        s.push(num);
                    }
                    if(tokens[i] == "*"){
                        int num = num2 * num1;
                        s.push(num);
                    }
                    if(tokens[i] == "/"){
                        int num = num2 / num1;
                        s.push(num);
                    }
                }
                else{
                    s.push(atoi(tokens[i].c_str()));
                }
            }
            int ans = s.top();
            return ans;
        }
    };
    复制代码
  • 相关阅读:
    [bzoj2038] [2009国家集训队]小Z的袜子
    浅谈莫队
    [bzoj2754] [SCOI2012]喵星球上的点名
    [bzoj3676] [APIO2014]回文串
    [bzoj5472] 数列
    [bzoj5457] 城市
    [bzoj1023] [SHOI2008]cactus仙人掌图
    [bzoj2125] 最短路
    [bzoj5473] 仙人掌
    读《深入理解Elasticsearch》点滴-查询评分
  • 原文地址:https://www.cnblogs.com/yechanglv/p/6930994.html
Copyright © 2020-2023  润新知