算法第九天|栈与队列基础、用栈实现队列LeetCode232、用队列实现栈LeetCode225、有效的括号LeetCode20、删除字符串中所有相邻重复项LeetCode1047

今日总结:

        整体简单,需要复习栈与队列的使用场景:先进后出、先进先出,

        需要复习栈与队列常用的一些方法

        栈的基础操作:

                1、压栈push()

                2、弹栈pop()

                3、查看栈顶:top()

                4、栈是否为空 empty()

        队列的基础操作:

                1、入队push()

                2、出队pop()

                3、查看队头front()

                4、查看队尾back()

                5、队列是否为空 empty()

                6、队列大小size()

栈与队列基础

栈的声明:

#include <stack>
stack <类型> 名称
push向栈顶插入元素
pop的弹出栈顶元素

        栈不是容器,而是容器适配器(栈的底层是通过其他的容器实现的,对外提供统一的接口)

        栈的底层容器可以是:vector、deque、list,如果没有指明具体的底层实现,默认使用deque双端队列为栈的底层结构也可以自行指定栈的底层容器:

std :: stack<int,std :: vector<int>> third //使用vector为底层容器实现栈

        栈的特点是先进后出,没有迭代器,不能遍历所有元素

使用数组实现栈 

//定义栈的数组为stk,tt为栈顶的下标,初始为0
int stk[N],tt=0;
//栈顶插入一个元素
void add(int x)
{
    stk[++  tt] =x;
}
//栈顶删除一个元素pop
void remove()
{
    tt--;
}
//判断栈是否为空
void is_empty()
{
    if(tt>0)printf("不空");
    else printf("空");
}
//获取栈顶元素
void query()
{
    printf("%d",stk[tt]);
}

队列

       先进先出,也是容器适配器 在默认情况下也是使用deque实现的,也可以通过list等实现

std :: queue<int,std :: list<int>> third //使用list为底层容器实现队列

双端队列:

*#include <deque>头文件deque包含双端队列

        deque是双端队列支持在两端高效插入和删除元素的连续线性存储空间,像是vector与queue的组合,与vector相比,deque在头部增删元素仅需O(1)的时间,与queue相比,deque像数组一样支持随机访问。

        可以尾插、头插、队尾弹出、队头弹出,支持随机访问[]

        begin/end,返回头/尾迭代器

        front/back队头/队尾元素

        push_back从队尾入队

        push_front从队头入队

        pop_back从队尾弹出

        pop_front从队头弹出

        clear清空队列

用栈实现队列

题目链接:LeetCode232、用栈实现队列

整体思路:

        栈:先进后出

        队列:先进先出

        ​​​​所以可以使用两个栈,一个用于接收输入的值,一个用于输出队头的值

        当要输入时,直接将值输入到接收栈的栈顶

        当要输出时,如果输出栈有值就输出栈顶并删除,如果输出栈为空,将输入栈的所有值从栈顶弹出,让输出栈全部接收,从而实现元素从输入栈的栈尾到输出栈的栈顶的翻转,实现先进先出

class MyQueue {
public:
    //定义一个入栈,一个转换的出栈
    stack <int> stkin;
    stack <int> stkout;
    MyQueue() {
        
    }
    
    void push(int x) {
        stkin.push(x);
        
    }
    
    int pop() {
        int top = this->peek();
        stkout.pop();
        return top;
        
    }
    
    int peek() {
        if(stkout.empty())
        {
            while(!stkin.empty())
            {
                stkout.push(stkin.top());
                stkin.pop();
            }
            
        }
        return stkout.top();
        
    }
    
    bool empty() {
        if(stkin.empty()&&stkout.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();
 */

 LeetCode225、用队列实现栈

题目链接:

整体思路:

        使用两个队列,队列A用于正常记录入栈,队列B用于在弹出栈顶、获取栈顶元素的时候,将A的除去最后的队尾元素全部加入到B中,然后获取A的队头元素,之后再将B的元素返还给A

class MyStack {
    //没有好的方法,使用两个队列,队列A用于接收元素
    //队列B用于在删除、获取栈顶元素时,将队列A中除最后一个元素全部移动到队列B,将A中队头输出
public:
    //定义两个队列
    queue <int> A;
    queue <int> B;
    MyStack() {

        
    }
    
    void push(int x) {
        A.push(x);
        
    }
    
    int pop() {
        int size = A.size()-1;
        while(size--)
        {
            B.push(A.front());
            A.pop();
        }
        //A剩余一个元素
        int C = A.front();
        // B.push(A.front());
        A.pop();
        while(!B.empty())
        {
            A.push(B.front());
            B.pop();
        }
        return C;
        
    }
    
    int top() {
        int size = A.size()-1;
        while(size--)
        {
            B.push(A.front());
            A.pop();
        }
        //A剩余一个元素
        int C = A.front();
        B.push(A.front());
        A.pop();
        while(!B.empty())
        {
            A.push(B.front());
            B.pop();
        }
        return C;
        
    }
    
    bool empty() {
        return A.empty();//如果A是空的表示没有元素了,因为B只是记录一下,最终还是会回到A
        
    }
};

/**
 * 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();
 */

有效的括号

题目链接:LeetCode20、有效的括号

整体思路:

        因为是做括号匹配,所以可以将三种左括号放到栈中,当遇到右括号的时候与栈顶元素比较,如果匹配,栈顶弹出,不匹配说明出错

        但是需要注意细节问题:

        1、如果出现右括号就直接与栈顶比较会出现问题:栈是空的,没有栈顶-->加上限制条件,栈不为空的时候才能与右括号比较,栈为空,出现右括号直接返回false

        2、因为只有右括号匹不匹配,才会进行判断返不返回false,所以丢失了一种情况:在遍历完字符串后,栈中仍然有没有匹配的左括号-->在遍历完字符串后,需要判断栈是不是空栈。

class Solution {
    //使用栈的先进后出,从左到右获取括号
    //在获取括号时,判断与前一位是不是相同,不同就加入栈顶,相同就弹出栈顶,
    //遍历完之后,查看栈是不是空的
public:
    bool isValid(string s) {
        stack<char>stk;
        for(auto i :s)
        {
            if ((i=='('||i=='['||i=='{')) stk.push(i);//如果是左括号直接入栈

            else if(!stk.empty()&&i==')'&&stk.top()=='(')//匹配成功
                stk.pop();//删除栈顶
            else if(!stk.empty()&&i==']'&&stk.top()=='[')//匹配成功
                stk.pop();//删除栈顶
            else if(!stk.empty()&&i=='}'&&stk.top()=='{')//匹配成功
                stk.pop();//删除栈顶
            else return false;
        }
        return stk.empty();//如果栈中没有元素就是全部匹配
        
    }
};

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

题目链接:LeetCode1047、删除字符串中所有相邻重复项

整体思路:

        使用一个栈来判断栈顶和当前元素,整体简单

class Solution {
public:
    string removeDuplicates(string s) {
        //不相同就入栈,相同就不入栈,栈顶元素弹出
        
        stack <int> stk;

        for(auto i :s)
        {
            if(stk.empty())//空就直接入栈
                stk.push(i);
            else if(i==stk.top())
            {
                stk.pop();
            }
            else stk.push(i);
        }
        //需要返回,栈底在前
        string res;
        while(!stk.empty())
        {
            res +=stk.top() ;
            stk.pop();
        }
        reverse(res.begin(),res.end());
        return res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值