代码随想录算法训练营第十一天 | 20. 有效的括号、1047. 删除字符串中的所有相邻重复项、150. 逆波兰表达式求值

20. 有效的括号

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

文章讲解:代码随想录—20.有效的括号

思路:

因为三种括号一一匹配,所以本题最好的解决办法就是用栈。

不符合题意的情况有三种:1. 左括号多余 2. 右括号多余 3. 左右括号不匹配

因此可以先按顺序判断字符串中括号类型,如果是左括号,就向栈里传入对应的右括号;如果是右括号,就验证栈顶的右括号与字符串的右括号是否相同,不相同就返回 false。如果验证过程中栈提前变空,或者验证结束后栈内还有元素剩余,则返回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();
    }
};

时间复杂度:O(n)

空间复杂度:O(n)

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

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

文章讲解:代码随想录—1047. 删除字符串中的所有相邻重复项

思路:

本题和上一题有效括号的思路是一样的,都是把要查找的匹配项放进栈中,如果匹配就弹出。

class Solution {
public:
    string removeDuplicates(string s) {
        stack<char> st;
        for (auto i : s) {
            if (st.empty() || st.top() != i) st.push(i);
            else st.pop();
        }

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

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

时间复杂度:O(n)

空间复杂度:O(n)

优化在于,可以不用单独申请栈,直接用string就能解决问题。

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

时间复杂度:O(n)

空间复杂度:O(1)

150. 逆波兰表达式求值 

题目链接:Leetcode150. 逆波兰表达式求值

文章讲解:代码随想录—150. 逆波兰表达式求值

思路:

这个题的解法很多,可以用二叉树解决,可以用递归解决,在这里介绍栈解决方法

在前几个题的铺垫下,这个题变得异常简单。只是注意最后把 vector<string> 的元素推进到 long long 数据结构的栈中的时候,要进行转换,用 stoll 可以把 string 类型转换成 long long 类型。

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

时间复杂度:O(n)

空间复杂度:O(n)

总结

栈适用于查找匹配和匹配消除的题,递归问题基本也都能用栈解决。

在企业项目开发中,尽量不要使用递归,在项目比较大的时候,由于参数多,全局变量等等,使用递归很容易判断不充分return的条件,非常容易无限递归(或者递归层级过深),造成栈溢出错误

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值