Bootstrap

代码随想录算法训练营第十天 | 232.用栈实现队列、 225. 用队列实现栈、20. 有效的括号、 1047. 删除字符串中的所有相邻重复项

1、栈和队列理论基础

栈和队列是STL(C++标准库)里面的两个数据结构。
:先进后出
在这里插入图片描述
栈提供push 和 pop 等等接口,所有元素必须符合先进后出规则,所以栈不提供走访功能,也不提供迭代器(iterator)。 不像是set 或者map 提供迭代器iterator来遍历所有元素。

栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可插拔的(也就是说我们可以控制使用哪种容器来实现栈的功能)
所以STL中栈往往不被归类为容器,而被归类为container adapter(容器适配器)

队列:先进先出的数据结构,同样不允许有遍历行为,不提供迭代器, SGI STL中队列一样是以deque为缺省情况下的底部结构。

也可以指定list 为起底层实现,初始化queue的语句如下:

std::queue<int, std::list> third; // 定义以list为底层容器的队列
所以STL 队列也不被归类为容器,而被归类为container adapter( 容器适配器)。

2、用栈实现队列

在这里插入图片描述

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

    }
    void push(int x) {
        stIn.push(x);
    } 
    int pop() { 
        if(stOut.empty()){
            while(!stOut.empty()){
                stOut.push(stIn.top());
                stIn.pop();
            }
        }
        int result = stOut.top();
        stOut.pop();
        return result;
    }  
    int peek() {
        int res = this->pop();
        stOut.push(res);
        return res;
    }   
    bool empty(){
        return stIn.empty() && stOut.empty();
    }
};

if (stOut.empty())
是C++中的条件判断语句的写法,用于检查 stOut 这个栈(std::stack)是否为空。

这里,stOut 是一个 std::stack 类型的对象,它是C++标准模板库(STL)中的一个容器适配器,提供了后进先出(LIFO)的数据结构。std::stack 提供了多种成员函数来操作栈,其中 empty() 是其成员函数之一。

empty() 成员函数的作用是检查栈是否为空。如果栈为空(即不包含任何元素),则 empty() 函数返回 true;如果栈不为空(即包含至少一个元素),则返回 false。

因此,if (stOut.empty()) 这行代码的意思是:“如果 stOut 栈为空,则执行接下来的代码块(即 if 语句的大括号 {} 中的代码)”。

stIn.top() 调用stIn栈的top()成员函数。top()函数返回栈顶元素的引用(但不移除该元素)。如果stIn不为空,则stIn.top()将返回栈顶元素的值或引用。

stOut.push(…) 调用stOut栈的push()成员函数。push()函数接受一个参数(即要添加到栈顶的元素),并将其压入栈中。

stIn.pop(); 用于移除栈顶的元素
这通常是在你已经使用 stIn.top() 访问了栈顶元素的值之后进行的,以避免内存泄漏或重复处理相同的元素。

3、用队列实现栈

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

    }
    
    void push(int x) 
    {
        que1.push(x);
    }
    
    int pop() 
    {
        int size = que1.size();
        size--;
        while(size--)
        {
            que2.push(que1.front());
            que1.pop();
        }
        int result = que1.front();
        que1.pop();
        que1 = que2;
        while(!que2.empty())
        {
            que2.pop();
        }
        return result;
    }
    
    int top() 
    {
        return que1.back();
    }
    
    bool empty() 
    {
        return que1.empty();
    }
};

优化后采用一个队列来操作

class MyStack {
public:
    queue<int> que;
    /** Initialize your data structure here. */
    MyStack() {

    }
    /** Push element x onto stack. */
    void push(int x) {
        que.push(x);
    }
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        int size = que.size();
        size--;
        while (size--) { // 将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部
            que.push(que.front());
            que.pop();
        }
        int result = que.front(); // 此时弹出的元素顺序就是栈的顺序了
        que.pop();
        return result;
    }

    /** Get the top element. */
    int top() {
        return que.back();
    }

    /** Returns whether the stack is empty. */
    bool empty() {
        return que.empty();
    }
};

4、有效的括号

第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false

第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false

第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false

那么什么时候说明左括号和右括号全都匹配了呢,就是字符串遍历完之后,栈是空的,就说明全都匹配了。

但还有一些技巧,在匹配左括号的时候,右括号先入栈,就只需要比较当前元素和栈顶相不相等就可以了,比左括号先入栈代码实现要简单的多了!

class Solution {
public:
    bool isValid(string s) 
    {
        if(s.size()%2 != 0) return false;
        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() || st.top() != s[i]) return false;
            else st.pop(); 
        }
        return st.empty();
    }
};

else if (st.empty() || st.top() != s[i]) return false;
此处要先判断栈是否为空,如果先调取当前栈栈顶元素,如果为空,相当于操作了空栈,则会异常。
else st.pop(); 这个相当于对对碰消除。
如果遍历完还不为空,相当于左括号多了

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

在这里插入图片描述

class Solution {
public:
    string removeDuplicates(string S) 
    {
      string result;
        for(char s:S)
        {
            if(result.empty() || result.back() != s)
            {
                result.push_back(s);
            }else
            {
                result.pop_back();
            }
        }
        return result;
    }
};
;