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

day 11 第五章 栈与队列

今日内容:

● 20. 有效的括号

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

● 150. 逆波兰表达式求值


详细布置

20. 有效的括号

【链接】(文章,视频,题目)

讲完了栈实现队列,队列实现栈,接下来就是栈的经典应用了。

大家先自己思考一下 有哪些不匹配的场景,在看视频 我讲的都有哪些场景,落实到代码其实就容易很多了。

题目链接/文章讲解/视频讲解:https://programmercarl.com/0020.%E6%9C%89%E6%95%88%E7%9A%84%E6%8B%AC%E5%8F%B7.html

【第一想法与实现(困难)】直接实现一个栈,发现需要考虑的边界情况较多,代码稍长,不易理解

【看后想法】

  • 不匹配的情况有三种:多余左括号,多余右括号,左右数目对但类型不对

  • early return,早返回:字符串长度必须为偶数才可能匹配

  • 检测到左括号,但是栈压入右括号,便于出栈的栈顶对比

  • 明确栈中存放的内容:等待配对的左括号(但是形式上换成了相应的右括号)

【实现困难】

【自写代码】

class Solution {
public:
    bool isValid(string s) {
        // 更优雅的栈配对。栈存放的内容是等待配对的左括号(但是形式上换成了相应的右括号)
        if (s.size() % 2 != 0) {
            return false;
        }
        std::stack<char> st;
        for (char c : s) {
            if (c == '(') {
                st.push(')');
            } else if (c == '[') {
                st.push(']');
            } else if (c == '{'){
                st.push('}');
            } else if (st.empty() || st.top() != c) {
                // 空栈,缺少左括号;不等说明不配对
                return false;
            } else { // 相等说明左右匹配,弹出栈顶
                st.pop();
            }
        }
        return st.empty(); // 最后栈应该空,非空说明多余左括号
    }
};

【收获与时长】35min


【链接】(文章,视频,题目)

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

栈的经典应用。

要知道栈为什么适合做这种类似于爱消除的操作,因为栈帮助我们记录了 遍历数组当前元素时候,前一个元素是什么。

题目链接/文章讲解/视频讲解:代码随想录

【第一想法与实现(困难)】

  • 暴力,看成类似左右括号配对,配对成功的在栈中删去

  • 代码实现的时候自己用了字符串原地修改,由于有额外的使用一个栈,空间复杂度还是O(N)

  • 将栈转化回到字符串的时候,下标要特别注意

【看后想法】

  • 实现基本一致。使用栈的可以另外定义新的返回字符串,因为已经用了O(N)空间的栈,所以空间利用都差不多

  • 还可以用新的字符串自身作为栈

【实现困难】无

【自写代码】

class Solution {
public:
    string removeDuplicates(string s) {
        // 使用栈
        std::stack<char> st;
        for (char c : s) {
            if (st.empty() || st.top() != c) {
                st.push(c);
            } else {
                st.pop();
            }
        }
        string res = "";
        while (!st.empty()) {
            res += st.top();
            st.pop();
        }
        std::reverse(res.begin(), res.end());
        return res;
    }
};

【收获与时长】40min


150. 逆波兰表达式求值

【链接】(文章,视频,题目)

本题不难,但第一次做的话,会很难想到,所以先看视频,了解思路再去做题

题目链接/文章讲解/视频讲解:代码随想录

【第一想法与实现(困难)】想不太出来的,直接看题解

【看后想法】

  • 用栈存数字,遇到运算符就弹出两个数字

  • 注意弹出数字在运算时候的顺序,特别是除法,没有交换律

【实现困难】

【自写代码】

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        // 栈存放数字,遇到运算符取两个数字进行计算并压入结果
        std::stack<long long> st;
        for (const std::string& s : tokens) {
            if (s == "+" || s == "-" || s == "*" || s == "/") {
                // 注意弹出顺序,特别是num1 / num2
                long long num2 = st.top();
                st.pop();
                long long num1 = st.top();
                st.pop();
                if (s == "+") {
                    st.push(num1 + num2);
                } else if (s == "-") {
                    st.push(num1 - num2);
                } else if (s == "*") {
                    st.push(num1 * num2);
                } else if (s == "/") {
                    st.push(num1 / num2);
                }
            } else {
                st.push(std::stoll(s));
            }
        }
        long long res = st.top();
        st.pop();
        return res;
    }
};

【收获与时长】40min

特别注意,力扣题目描述已经说明了,数字本身是最多32位的。此处补充一下,int, long int, long long int的位数区别
一般int = long int,32位,4字节,±2^31 ~= ±2e9
long long int,64位,8字节,±2^63 ~= ±1e19
由于数字本身可能是32位,已经超出了普通int的正负31位,再加上四则运算,所以用long long。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值