《代码随想录》栈和队列

题目:用栈实现队列

我这里把stIn作为了主栈,stOut作为了辅助栈,而《代码随想录》则是导入到stOut就不管了,这样反而能在peek代码中复用,但我的好理解

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

    }
    
    void push(int x) {
        stIn.push(x);
    }
    
    int pop() {
        while (!stIn.empty()) {
            int node = stIn.top();
            stIn.pop();
            stOut.push(node);
        }

        int result = stOut.top();
        stOut.pop();

        while (!stOut.empty()) {
            int node = stOut.top();
            stOut.pop();
            stIn.push(node);
        }

        return result;
    }
    
    int peek() {
        while (!stIn.empty()) {
            int node = stIn.top();
            stIn.pop();
            stOut.push(node);
        }

        int result = stOut.top();

        while (!stOut.empty()) {
            int node = stOut.top();
            stOut.pop();
            stIn.push(node);
        }

        return result;
    }
    
    bool empty() {
        return stIn.empty() && stOut.empty();
    }
};

题目:用队列实现栈

或者top()函数直接用que.back即可

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

    }
    
    void push(int x) {
        que.push(x);
    }
    
    int pop() {
        int size = que.size() - 1;
        while (size--) {
            que.push(que.front());
            que.pop();
        }

        int result = que.front();
        que.pop();
        return result;
    }
    
    int top() {
        int result = this->pop();

        que.push(result);

        return result;

    }
    
    bool empty() {
        return que.empty();
    }
};

题目:有效的括号

class Solution {
public:
    bool isValid(string s) {
        //思路:首先判断是不是左边的括号,如果是左边的括号,去在栈中分别加入对应的右边的括号,然后只要一遇到不是左边括号的,那就是判断右边的和栈里已经有的右边括号匹配不匹配,如果匹配,那就出栈
        //true的结果:遍历完以后,如果栈是空,那就是都是有效的括号
        //错误1:如果栈最后剩下了,那就是左括号多了
        //错误2:如果还没遍历完s,栈就没了,那就是右括号多了
        //错误3:如果是没匹配上,那就是不匹配

        stack<char> st;
        for (char ss : s) {
            if (ss == '(') {
                st.push(')');
            } else if (ss == '[') {
                st.push(']');
            } else if (ss == '{') {//上面是针对三种不同的左边括号把右边括号加入栈
                st.push('}');
            } else if (st.empty()) {//错误2:数组还有,但是栈没了
            //注意,这里应该把st.empty的函数写在前面,为什么呢?因为后面还有st.top的函数,如果栈为空,但是用了st.top函数,就会报错,因此应该先判断栈空
                return false;
            } else if (ss != st.top()) {//错误3:没匹配上
                return false;
            } else if (ss == st.top()) {//是有效的括号,那就要出栈
                st.pop();
            } 
        }

        if (st.empty()) {//全是有效的括号,那就是true
            return true;
        } else {//错误1:数组没了,但是栈还有
            return false;
        }
    }
};

题目:删除字符串中的所有相邻重复项

class Solution {
public:
    string removeDuplicates(string s) {
        //思路:其实就是对对碰,我先遍历这个数组,如果这个数组的该元素能匹配上栈的top元素,那就消掉(即出栈),如果匹配不上,放入栈中
        //消完了以后遇到第二个问题,这是个栈,但是他要的是个字符串,栈应该如何转化为字符串,可以用加号运算符拼接字符串,然后反转一下,这样时间复杂度是
        stack<char> st;
        for (char ss : s) {
            if (st.empty() || ss != st.top()) {//如果匹配不上,放入栈中
                st.push(ss);
            } else {//如果这个数组的该元素能匹配上栈的top元素,那就消掉(即出栈)
                st.pop();
            }       
        }

        string result = "";
        while (!st.empty()) {
            result += st.top();
            st.pop();
        }

        reverse(result.begin(), result.end());
        return result;
    }
};

更近一步,可以直接用vector来模拟栈,代码如下

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

题目:逆波兰表达式求值

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        //去遍历这个数组如果不是符号(即数字),那就去加入到栈中,然后一旦遍历到符号,那就从栈中取出来两个数,然后做了运算以后的结果又放入栈中,最后算出来多少就是多少
        stack<int> st;

        for (string s : tokens) {
            if (s != "+" && s != "-" && s != "*" && s != "/") {//如果是数字,那就放进去栈中
                st.push(stoi(s));
            } else {
                //拿出来这两个数字
                int num1 = st.top();
                st.pop();
                int num2 = st.top();
                st.pop();

                int res;//定义出来两个数的运算结果
                if (s == "+") {
                    res = num2 + num1;
                } else if (s == "-") {
                    res = num2 - num1;
                } else if (s == "*") {
                    res = num2 * num1;
                } else if (s == "/") {
                    res = num2 / num1;
                }

                st.push(res);//把结果最后放进去栈
            }
        }

        return st.top();
    }
};

题目:滑动窗口最大值

题目:前K个高频元素

总结:用栈实现匹配问题

总结:栈中的字符怎么变成一个字符串

利用加号运算符来拼接,然后反转(从《题目:删除字符串中的所有相邻重复项》学到的)

string result = "";
while (!st.empty()) {
    result += st.top();
    st.pop();
}

reverse(result.begin(), result.end());

总结:队列解决的是什么样的问题

总结:优先级队列

这个很适合求前K个最大值这种问题,链接:《堆排序》二叉树的题目中《二叉搜索树中的众数》也是类似的,可以理解成这些元素的,出现频率最高的第一个元素,而这个问题中其实我用的是把map转化为vector,然后排了序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值