文章链接: 栈与队列理论基础 232.用栈实现队列 225. 用队列实现栈 20. 有效的括号 1047. 删除字符串中的所有相邻重复项

视频链接: 232.用栈实现队列 225. 用队列实现栈 20. 有效的括号 1047. 删除字符串中的所有相邻重复项

题目链接: 232.用栈实现队列 225. 用队列实现栈 20. 有效的括号 1047. 删除字符串中的所有相邻重复项

(备用链接: https://programmercarl.com/%E6%A0%88%E4%B8%8E%E9%98%9F%E5%88%97%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html

栈与队列理论基础:

一下为栈与队列的简单思维导图,并不完善,日后系统学习后再进行补充。

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

清晰版本请挪步幕布链接: https://mubucm.com/doc/2P0Yk-wWpzI

思路:

232.用栈实现队列

实现进队列操作:

直接塞进”进栈“中(stIn);


实现删除元素操作:
  1. stOut为空时,将stIn中的全部数据导入stOut中(要将stIn中的数据全部删除)
  2. 返回并删除stOut中的第一个元素(栈顶);


实现返回队列开头元素操作:

步骤与上一个操作一样,不同点在于要将删除的元素重新push回来;

实现对队列的判空操作:

直接对“进栈”和“出栈”判空;

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

    MyQueue() {

    }
    
    void push(int x) {
        stIn.push(x);
    }
    
    int pop() {
        if(stOut.empty()){ 
            // 当stOut为空的时候,再从stIn中导入数据
            // 导入数据时,要导入stIn的全部数据
            while(!stIn.empty()){
                stOut.push(stIn.top()); // 讲数据放入”出栈“中
                stIn.pop(); // 删除“进栈”中的数据
            }
        }
        int result = stOut.top();
        stOut.pop();
        return result;
    }
    
    int peek() {
        int res = this->pop(); // 直接使用已有的pop函数
        stOut.push(res); // 因为pop()弹出了元素res,所以再添加回去
        return res;
    }
    
    bool empty() {
        return stIn.empty() && stOut.empty();
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.

225.用队列实现栈

难点在于pop()函数。所以接下来只论述如何实现这一元素。

  1. 先将size - 1 个元素放到队列后并弹出;
  2. 返回原队列最后一个元素(即新队列第一个元素),并删除;

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

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

    }
    
    void push(int x) {
        que.push(x);
    }
    
    int pop() {
        int size = que.size();
        size--; // --后的size就为需要放在队列后面的元素个数
        while(size--){
        // 将队列前面的元素一个个放入队列的后边(两个步骤)
            que.push(que.front()); // 增加到后面
            que.pop(); // 删除前面
        }
        int result = que.front();
        que.pop();
        return result;
    }
    
    int top() {
        return que.back();
    }
    
    bool empty() {
        return que.empty();
    }
};

/**
 * 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();
 */
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.

20.有效的括号

不匹配的情况分为以下几种:

  1. 还没遍历完栈就为空(右括号多了)
  2. 遍历到的右括号与栈顶元素不一样(左右括号不匹配)
  3. 遍历完了但是栈里还有元素(右括号不够)
class Solution {
public:
    bool isValid(string s) {
        if (s.size() % 2 == 1) // 字符串长度为奇数,一定匹配不成功
            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() || s[i] != st.top()) { 
            // 第一种:还没遍历完栈就为空(右括号多了)
            // 第二种:遍历到的右括号与栈顶元素不一样(左右括号不匹配)
                return false;
            } else {
                st.pop();
            }
        }
        return st.empty();
        // 第三种:遍历完了但是栈里还有元素(右括号不够)
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

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


class Solution {
public:
    string removeDuplicates(string s) {
        stack<int> st;
        for (char i : s) {
            if (st.empty() || i != st.top()) {
                st.push(i);
            } else {
                st.pop();
            }
        }
        string result;
        while (!st.empty()) {
            result += st.top();
            st.pop(); // 别忘了
        }
        reverse(result.begin(), result.end());
        return result;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

困难:

232.用栈实现队列

: int res = this->pop(); 这一代码是什么意思?

This-> 表示在类本身内部使用本类的属性或者方法

注意:是一个指针,要用->来访问成员变量或成员函数。


225.用队列实现栈

无。


20.有效的括号

无。


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

无。


今日收获:

经过这几道题,对栈的操作有了一定的了解,但是在做题时并不能看出这道题是用栈进行求解,还是得多加练习。