【面试经典 150 | 栈】基本计算器

写在前面

本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更……

专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删:

  • Tag:介绍本题牵涉到的知识点、数据结构;
  • 题目来源:贴上题目的链接,方便大家查找题目并完成练习;
  • 题目解读:复述题目(确保自己真的理解题目意思),并强调一些题目重点信息;
  • 解题思路:介绍一些解题思路,每种解题思路包括思路讲解、实现代码以及复杂度分析;
  • 知识回忆:针对今天介绍的题目中的重点内容、数据结构进行回顾总结。

Tag

【栈】


题目来源

224. 基本计算器


解题思路

本题参考 官方题解

方法一:括号展开+栈

思路

由于字符串除了数字与括号外,只有加号和减号两种运算符。因此,如果展开表达式中所有的括号,则得到的新表达式中,数字本身不会发生变化,只是每个数字前面的符号会发生变化。

因此,我们考虑使用一个取值为 {−1,+1} 的整数 sign 代表「当前」的符号。根据括号表达式的性质,它的取值:

  • 与字符串中当前位置的运算符有关;
  • 如果当前位置处于一系列括号之内,则也与这些括号前面的运算符有关:每当遇到一个以 −-− 号开头的括号,则意味着此后的符号都要被「翻转」。

考虑到第二点,我们需要维护一个栈 ops,其中栈顶元素记录了当前位置所处的每个括号共同作用下的符号。例如,对于字符串 1+2+(3-(4+5))

  • 扫描到 1+2 时,由于当前位置没有被任何括号所包含,则栈顶元素为初始值 +1
  • 扫描到 1+2+(3 时,当前位置被一个括号所包含,该括号前面的符号为 + 号,因此栈顶元素依然 +1
  • 扫描到 1+2+(3-(4 时,当前位置被两个括号所包含,分别对应着 + 号和 号,由于 + 号和 号合并的结果为 号,因此栈顶元素变为 −1

在得到栈 ops 之后, sign 的取值就能够确定了:如果当前遇到了 + 号,则更新 sign = ops.top();如果遇到了遇到了 号,则更新 sign = ops.top()

然后,每当遇到 ( 时,都要将当前的 sign 取值压入栈中;每当遇到 ) 时,都从栈中弹出一个元素。这样,我们能够在扫描字符串的时候,即时地更新 ops 中的元素。

代码

class Solution {
public:
    int calculate(string s) {
        // 只有正负号,因此数字不会改变,只是每个数字前面的符号会变
        stack<int> stk;
        int sign = 1;
        stk.emplace(sign);
        int i = 0, n = s.size();

        int ret = 0;
        while(i < n) {
            if (s[i] == ' ') {
                ++i;
            }
            else if(s[i] == '+') {
                sign = stk.top();
                ++i;
            }
            else if (s[i] == '-') {
                sign = -stk.top();
                ++i;
            }
            else if (s[i] == '(') {
                stk.emplace(sign);
                ++i;
            }
            else if (s[i] == ')') {
                stk.pop();
                ++i;
            }
            else {
                long long num = 0;
                while(i < n && s[i] >= '0' && s[i] <= '9') {
                    num = num * 10 + s[i] - '0';
                    ++i;
                }
                ret += sign * num;
            }
        }
        return ret;
    }
};

复杂度分析

时间复杂度: O ( n ) O(n) O(n) n n n 是字符串 s 的长度。

空间复杂度: O ( n ) O(n) O(n)


写在最后

如果您发现文章有任何错误或者对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

如果大家有更优的时间、空间复杂度的方法,欢迎评论区交流。

最后,感谢您的阅读,如果有所收获的话可以给我点一个 👍 哦。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wang_nn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值