算法训练 day11 | 20. 有效的括号 1047. 删除字符串中的所有相邻重复项 150. 逆波兰表达式求值

本文介绍了如何利用栈解决编程中的三个问题:检查有效括号对、删除字符串中的相邻重复项以及逆波兰表达式的求值。通过栈的特性,简化了这些问题的算法实现,时间复杂度和空间复杂度均为O(n)。
摘要由CSDN通过智能技术生成

20. 有效的括号

题目链接:有效的括号

视频讲解:栈的拿手好戏

        栈的特殊结构,非常适合做对称匹配类的题目。

首先要弄清楚有几种不匹配的情况。其实总共就三种:

1、“( [ { } ] ( )” 左边括号多余;

2、“( [ { ] ] )” 括号类型不匹配;

3、“( [ { } ] ) ) )” 右边括号多余;

弄清楚这几种情况,那么怎么有效的运用栈呢?因为存在左括号就要有个有括号跟它匹配,在遍历字符串的时候,碰到左括号我们就可以往栈里放一个右括号,这样在字符串中寻找右括号时可以直接与栈中元素进行比较,不用过多的操作。

接下来就是讨论这几种情况了:

第一种情况:已经遍历完了,但是占中还有元素,说明没有足够的右括号与串中的左括号匹配,return false;

第二种情况:在遍历字符串时,没有与之匹配的字符,return false;

第三种情况:还没遍历完,栈已经空了,说明没有足够的左括号与右括号匹配,return false;

// 时间复杂度: O(n)
// 空间复杂度: O(n)
class Solution {
public:
    bool isValid(string s) {
        stack<char> st;
        if (s.size() % 2 != 0) // 字符串为奇数可难听不满足条件
            return false;
        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(); // 遍历完栈不为空 false,栈空 true
    }
};

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

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

视频讲解:栈的好戏还在继续

        删除相邻重复项,其实就是匹配前后元素是否一样,用栈再好不过了。那么栈里该怎么放元素呢?

先遍历字符串中的元素,如果栈中没有与之相同的就把它放入栈中,如果栈中有就把从栈里删除该元素,直到遍历完,栈里的元素就是没有重复项的字符串了。但是,此时栈中元素与所求字符串顺序相反,就还得用个字符串把栈中元素倒序排列。其实,不需这么麻烦,我们可以直接定义一个字符串,让它发挥栈的功能。如前说述,当需要入栈时,此时对应的就是把该元素放到新定义的字符串串尾,需要删除时也是删除串尾,这样最后得出的字符串就是所需答案。

// 时间复杂度: O(n)
// 空间复杂度: O(n)
class Solution {
public:
    string removeDuplicates(string s) {
        string st;
        for (auto i : s)
        {
            if (st.empty() || i != st.back())
            {
                st.push_back(i);
            }
            else st.pop_back();
        }
        return st;
    }
};

150. 逆波兰表达式求值

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

视频讲解:栈的最后表演!

        首先要明白逆波兰表达式,其实它就是二叉树中的后续遍历。把运算符作为中间节点,按照后续遍历的规则画出一个二叉树。但我们没必要用二叉树解决问题。只需要一个栈,遍历字符串时,遇到数字就放入栈中,遇到运算符,就把栈顶两个元素用该运算符计算,得到的答案继续入栈中,直到栈里只剩一个元素,就是所求的答案。

注意:字符串类型转成整型

// 时间复杂度: O(n)
// 空间复杂度: O(n)
class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<long long> st;
        for (int i = 0; i < tokens.size(); i++)
        {
            if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/")
            {
                long long n1 = st.top();
                st.pop();
                long long n2 = st.top();
                st.pop();
                if (tokens[i] == "+")
                    st.push(n1 + n2);
                if (tokens[i] == "-")
                    st.push(n2 - n1);
                if (tokens[i] == "*")
                    st.push(n1 * n2);
                if (tokens[i] == "/")
                    st.push(n2 / n1);
            }
            else
            {
                st.push(stoll(tokens[i]));
            }
        }
        int res = st.top();
        st.pop();
        return res;
    }
};

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值