LeetCode刷题笔记【7】:栈&队列专题-2(有效的括号, 删除字符串的所有相邻重复项, 逆波兰表达式求值)

前置知识

参见前文

参考文章:LeetCode刷题笔记【6】:栈&队列专题-1(用栈实现队列, 用队列实现栈)

20. 有效的括号

题目描述

截图

LeetCode链接:https://leetcode.cn/problems/valid-parentheses/description/

解题思路

思路: 创建一个栈, 遍历字符串, 每次遇到左括号就入栈, 遇到右括号就弹出栈顶元素进行匹配
匹配失败返回false, 最后栈非空false, 否则true

代码

这里可以选择是在入栈的时候进行左右括号的转换, 还是在出栈检查的时候进行转化.
我这里是在出栈检查的时候进行了转化(写了一个change函数进行对比)
但是也可以在入栈的时候, 入栈相反的括号.

class Solution {
public:
    char change(char c){
        if(c==')')
            return '(';
        else if(c=='}')
            return '{';
        else if(c==']')
            return '[';
        return '`';
    }
    bool isValid(string s) {
        stack<char> st;
        for(char c : s){
            if(c=='(' || c=='{' || c=='[')
                st.push(c);
            else if(st.empty() || st.top()!=change(c)){
                return false;
            }else{
                st.pop();
            }
        }
        if(!st.empty())
            return false;
        return true;
    }
};

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

题目描述

截图

LeetCode链接:https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/description/

用队列解题

思路: 可以使用数组, 但是数组的erase操作复杂度实在太高
所以使用queue进行操作

class Solution {
public:
    // void printQ(queue<char> q){
    //     while(!q.empty()){
    //         cout << ' ' << q.front() ;
    //         q.pop();
    //     }
    //     cout << endl;
    // }
    string removeDuplicates(string s) {
        int size=s.size();
        queue<char> q;
        for(char c : s){
            q.push(c);
        }
        bool flag=true;
        while(flag){
            // printQ(q);
            flag = false;
            size = q.size();
            queue<char> tmpQ;
            while(!q.empty()){
                char tmp = q.front();
                q.pop();
                if(tmp==q.front()){
                    q.pop();
                    flag = true;
                }else{
                    tmpQ.push(tmp);
                }
            }
            swap(q,tmpQ);
        }
        string ans;
        while(!q.empty()){
            ans.push_back(q.front());
            q.pop();
        }
        return ans;
    }
};

用栈解题

反而是用queue超出时间限制, 学习题解后使用栈.

class Solution {
public:
    string removeDuplicates(string s) {
        stack<char> st;
        for(char c : s){
            if(st.empty() || c!=st.top()){
                st.push(c);
            }else{
                st.pop();
            }
        }
        string ans;
        while(!st.empty()){
            ans.push_back(st.top());
            st.pop();
        }
        reverse(ans.begin(), ans.end());
        return ans;
    }
};

用新字符串代替栈

能不能直接用string ans达到stack的效果呢?
这样就不用最后还将栈转化为字符串

class Solution {
public:
    string removeDuplicates(string s) {
        string ans;
        for(char c : s){
            if(ans.size()==0 || c!=ans[ans.size()-1]){
                ans.push_back(c);
            }else{
                // ans.erase(ans.size()-1);
                ans.pop_back();
            }
        }
        return ans;
    }
};

150. 逆波兰表达式求值

题目描述

截图

LeetCode链接:https://leetcode.cn/problems/evaluate-reverse-polish-notation/description/

解题思路

思路: 用栈解决
遇到数字就入栈, 遇到符号了就拿出栈顶的两个元素和那个符合进行计算, 结果再入栈

代码

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<long long> st;
        for(string c : tokens){
            if(c=="+" || c=="-" || c=="*" || c=="/"){
                long long nums1, nums2;
                nums2 = st.top();
                st.pop();
                nums1 = st.top();
                st.pop();
                if(c=="+")
                    st.push(nums1 + nums2);
                else if(c=="-")
                    st.push(nums1 - nums2);
                else if(c=="*")
                    st.push(nums1 * nums2);
                else if(c=="/")
                    st.push(nums1 / nums2);
            }else{
                st.push(stoll(c));
            }
        }
        return st.top();
    }
};

总结

什么时候使用栈?
总结这些题型可以发现: 在需要以特定的规律和顺序进行反复比较和存取操作的时候, 用栈会更方便.

本文参考:
20. 有效的括号
1047. 删除字符串中的所有相邻重复项
150. 逆波兰表达式求值

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值