【LeetCode】227. 基本计算器 II

227. 基本计算器 II(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

方法:双栈解法

思路

  • 我们可以使用两个栈 nums 和 ops

    • nums : 存放所有的数字
    • ops :存放所有的数字以外的操作
  • 然后从前往后做,对遍历到的字符做分情况讨论:

    • 空格 : 跳过
    • 数字 : 从当前位置开始继续往后取,将整一个连续数字整体取出,加入 nums
    • +、-、*、/ : 需要将操作放入 ops 中。在放入之前先把栈内可以算的都算掉(只有「栈内运算符」比「当前运算符」优先级高/同等,才进行运算),使用现有的 nums 和 ops 进行计算,直到没有操作,计算结果放到 nums。
  • 细节:可以通过 unordered_map 手动为运算符设置优先级,当遇到操作符号,如果栈内已经存在操作符,先比较它们的优先级,判断是否可以进行运算。

  • 我们可以通过例子来理解 只有「栈内运算符」比「当前运算符」优先级高/同等,才进行运算 是什么意思:

    • 因为我们是从前往后做的,假设我们当前已经扫描到 2 + 1 了(此时栈内的操作为 + )。

    • 如果后面出现的 + 2 或者 - 1 的话,满足「栈内运算符」比「当前运算符」优先级高/同等,可以将 2 + 1 算掉,把结果放到 nums 中;

    • 如果后面出现的是 * 2 或者 / 1 的话,不满足「栈内运算符」比「当前运算符」优先级高/同等,这时候不能计算 2 + 1。

代码

class Solution {
public:
    void replace(string &s) {
        int pos = s.find(" ");
        while(pos != -1) {
            s.replace(pos, 1, "");
            pos = s.find(" ");
        }
    }
    int calculate(string s) {
        // 存放数字的栈
        stack<int> nums;
        // 存放符号的栈
        stack<char> ops;
        // 定义符号的优先级
        unordered_map<char, int> imp_op = {
            {'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}
        };
        // 去除空格
        replace(s);
        // 开始遍历s
        for(int i=0; i<s.size(); ++i) {
            char c = s[i];
            // 如果遇到数字,将其之后的连续数字取出并存入nums
            if(isdigit(c)) {
                int cur_num = 0;
                int j = i;
                while(isdigit(s[j]) && j<s.size()) {
                    cur_num = cur_num * 10 + (s[j++] - '0');
                }
                nums.push(cur_num);
                i = j - 1;
            }
            // + - * /
            else {
                // 如果符号栈内有符号,需要先将可计算的算完
                while(!ops.empty() && imp_op[ops.top()] >= imp_op[c]) {
                    calc(nums, ops);
                }
                ops.push(c);
            }
        } 
        while(!ops.empty()) calc(nums, ops);
        return nums.top();
    }
    void calc(stack<int> &nums, stack<char> &ops) {
        if(nums.size() < 2 || ops.empty()) return ;
        int b = nums.top(); nums.pop();
        int a = nums.top(); nums.pop();
        char op = ops.top(); ops.pop();
        int res;
        if(op == '+')   res = a + b;
        else if(op == '-') res = a - b;
        else if(op == '*') res = a * b;
        else if(op == '/') res = a / b;
        nums.push(res);
    }
};

参考资料

  1. 【宫水三叶】使用「双栈」解决「究极表达式计算」问题
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值