栈和队列篇--代码随想录算法训练营第十天| 栈和队列基础知识,栈和队列常用操作,232.用栈实现队列,225. 用队列实现栈,20. 有效的括号,1047. 删除字符串中的所有相邻重复项

栈和队列基础知识

栈和队列常用操作

stack:栈

头文件: # include < stack > 模拟栈的功能和特点: 元素后进先出, 只能访问栈顶元素, 属于C++特殊容器

1、构造函数

stack <int> st, st1;//定义 int 类型的栈
stack <char> stch;//定义 char 类型的栈
stack <string> ststr;//定义 string 类型的栈
stack <int> st2(st);// 定义新容器, 拷贝 st 所有的元素
stack <int, vector<int> > st3;//底层使用 vector 容器实现栈, 默认是 deque    

2、成员函数

st.top();//返回栈顶元素
st.push(5);//在栈顶插入新元素 5
st.emplace(5);//在栈顶创建新元素 5
st.pop();//删除栈顶元素
st.size();//返回容器目前的元素个数
st.empty();//容器为空返回 true, 否则返回 false
st.swap(st1);//交换两个容器的内容

queue:队列

头文件: # include < queue > 模拟队列的功能和特点: 元素先进先出, 可以访问队列两端元素, 属于C++特殊容器

1、构造函数

queue <int> q, q1;//定义 int 类型的队列
queue <char> qch;//定义 char 类型的队列
queue <string> qstr;//定义 string 类型的队列
queue <int> q2(q);//定义新容器, 拷贝 q 所有的元素
queue <int, vector<int> > q3;//使用 vector 容器实现队列, 默认是 deque  

2、成员函数

q.front();//返回队列头部元素
q.back();//返回队列尾部元素
q.push(5);//在队列尾部插入新元素 5
q.emplace(5);//在队列尾部创建新元素 5
q.pop();//删除队列头部元素
q.size();//返回容器目前的元素个数
q.empty();//容器为空返回 true, 否则返回 false
q.swap(q1);//交换两个容器的内容

题目:

232.用栈实现队列

题目链接:232.用栈实现队列

讲解视频:栈的基本操作! | LeetCode:232.用栈实现队列

题目描述:

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty):

实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:

  • 你 只能 使用标准的栈操作 —— 也就是只有 push to toppeek/pop from topsize, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

示例 1:

输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]

解题思路:

 使用两个栈st1,st2。st1用于push操作,st2用于pop和peek操作,当用到pop和peek操作时要保证st1中所有元素都放入st2中

代码:

class MyQueue {
public:
    MyQueue() {
        
    }
    
    void push(int x) {
        s1.push(x);
    }
    
    int pop() {
        if(s2.empty()) 
            while(!s1.empty()) s2.push(s1.top()),s1.pop();
        int tp = s2.top();
        s2.pop();
        return tp;
    }
    
    int peek() {
        if(s2.empty()) 
            while(!s1.empty()) s2.push(s1.top()),s1.pop();
        return s2.top();
    }
    
    bool empty() {
        if(s1.empty() && s2.empty()) return true;
        return false;
    }
private:
    stack<int> s1;
    stack<int> s2;
};

/**
 * 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.用队列实现栈

题目链接:225.用队列实现栈

讲解视频:队列的基本操作! | LeetCode:225. 用队列实现栈

题目描述:

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppop 和 empty)。

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

注意:

  • 你只能使用队列的标准操作 —— 也就是 push to backpeek/pop from frontsize 和 is empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

示例:

输入:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]

解题思路:

 不能用第一题的思路,因为队列是先进先出机制。该题目使用一个队列即可模拟栈。

调用push操作时正常入队列;当调用pop/top操作时,将前n-1个数出队列并从重新从队尾入队,记录第n个数值,并对其进行出队列操作,如果是top则将第n个数再次从队尾入队,最后返回已记录的第n个数值。

代码:

class MyStack {
public:
    MyStack() {

    }
    
    void push(int x) {
        q1.push(x);
    }
    
    int pop() {
        int len = q1.size();
        len--;
        while(len--)
        {
            int tp = q1.front();
            q1.pop();
            q1.push(tp);
        }
        int x = q1.front();
        q1.pop();
        return x;
    }
    
    int top() {
        int len = q1.size();
        len--;
        while(len--)
        {
            int x = q1.front();
            q1.pop();
            q1.push(x);
        }
        int tp = q1.front();
        q1.pop();
        q1.push(tp);
        return tp;
    }
    
    bool empty() {
        if(q1.empty()) return true;
        else return false;
    }
private:
    queue<int> q1;
};

/**
 * 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.有效的括号

题目链接:20.有效的括号

讲解视频:栈的拿手好戏!| LeetCode:20. 有效的括号

题目描述:

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

示例 1:

输入:s = "()"
输出:true

示例 2:

输入:s = "(]"
输出:false

解题思路:

 使用栈数据结构。有如下几个思考点:

  1. s长度为偶数时才有可能正确
  2. 左括号一定要在右括号前入栈--um[tp]< um[c]
  3. 已结束后栈是否为空作为判断标准

代码:

class Solution {
public:
    bool isValid(string s) {
        if (s.size() % 2 != 0) return false; // 如果s的长度为奇数,一定不符合要求
        stack<char> st;
        unordered_map<char,int> um;
        um['('] = -1, um[')'] = 1;
        um['['] = -2, um[']'] = 2;
        um['{'] = -3, um['}'] = 3;
        for(auto c : s)
        {
            if(st.empty()) st.push(c);
            else
            {
                char tp = st.top();
                if(um[tp] < um[c] && um[tp] * (-1) == um[c]) st.pop();
                else st.push(c);
            }
            
        }
        if(st.empty()) return true;
        return false;
    }
};


1047.删除字符串中的所有

题目链接:1047.删除字符串中的所有

讲解视频:栈的好戏还要继续!| LeetCode:1047. 删除字符串中的所有相邻重复项

题目描述:

给出由小写字母组成的字符串 S重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:

输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。

解题思路:

 使用栈数据结构。每次入栈先检验数值与栈顶元素是否相等,相等就出栈,否则入栈。

最后将栈元素保存在字符串中,并反转字符串。

代码:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值