224. 基本计算器

224. 基本计算器
题目含义:实现一个基本的计算器,计算一个字符串表达式 s 并返回其值。s 由数字、+-()、和空格组成,而且 -(2 + 3) 这样的表达式是有效的。

在这个表达式中除了括号外,运算符就只有 +-。因此我们可以使用双栈来实现一个计算器,这两栈分别存储数字和运算符,分别记为 numStopsSt
此外,我们需要额外考虑 -(-1+5)-6 这种情况。这两种情况对应了 - 是字符串 s 的第一个字符或在 ( 的后面,那么我们在numSt 添加数字 0,则表达式就变成了 0-60-(0-1+5)

考虑完特殊情况,我们现在对表达式 s 从前往后遍历,将数字字符和运算符字符分开处理。假设当前遍历到的元素是 c = s[i]

  1. c(:直接放进 opsSt 栈中;
  2. c):计算现有的 opsStnumSt,直到遇到 ) 停止计算,将计算结果是放进 numSt 中,最后把栈顶元素 ) 弹出;
  3. c 是数字字符:若这个字符为 5255,那么我们需要利用 while 获取整个数字,然后存进 numSt 中;
  4. c 是运算符字符,根据上面讨论的情况,我们需要判断符号 - 是否在第一个位置或在 ( 后面,即 i==0 or s[i-1] in '(';接下来在添加新的运算符之前,可以先把现有的数字和运算符进行计算,再执行 opsSt.append(c)

当遍历完整个表达式,如果 opsSt 栈不为空,则我们把现有的元素继续计算;最后返回 numSt 的栈顶元素。

class Solution:
    def calculate(self, s: str) -> int:
        # (1+(4+555+2)-3)+(-6+8)  555 和 -6 
        numSt, opsSt = [], []
        s = s.replace(" ", "")  # 将所有的空格删除

        def calc():
            if len(numSt) < 2 or not opsSt:
                return   
            b, a, op = numSt.pop(), numSt.pop(), opsSt.pop()  # 注意a和b的位置
            numSt.append(a+b if op == '+' else a-b)
        
        i = 0
        while i < len(s):
            c = s[i]
            if c == '(':
                opsSt.append(c)
            elif c == ')':   
                while opsSt and opsSt[-1] != '(':
                    calc()      
                opsSt.pop()  # == '(' 
            else:
                if c.isdigit():
                    num = 0
                    while i < len(s) and s[i].isdigit():
                        num, i = num * 10 + int(s[i]), i+1
                    numSt.append(num)
                    i -= 1
                else:
                    # -(-4+5+2)  
                    if c in '-' and (i == 0 or s[i-1] in '('):
                        numSt.append(0)
                    while opsSt and opsSt[-1] != '(': 
                        calc()
                    opsSt.append(c)
            i += 1
        while opsSt:
            calc()    
        return numSt[-1]
/**
 * @param {string} s
 * @return {number}
 */
var calculate = function(s) {
    s = s.replace(/\s*/g, '');   // 返回一个新的字符串
    const numSt = [], opSt = [];
    const calc = () => {
        if (numSt.length < 2 || opSt.length === 0) return;
        const b = numSt.pop(), a = numSt.pop(), op = opSt.pop();
        numSt.push(op === '-' ? a - b : a + b);
    }
    const n = s.length;
    for (let i=0; i < n; i++) {
        const c = s[i];
        if (c === '(') opSt.push(c);
        else if (c === ')') {
            while (opSt.length > 0 && opSt.at(-1) !== '(') calc();
            opSt.pop();   // 移除 '('
        }
        else {
            if (/^[0-9]$/.test(c)) {
                let num = 0;
                // 从 s[i] 开始处理
                while (i < n && /^[0-9]$/.test(s[i])) num = num * 10 + Number(s[i]), i++;  
                numSt.push(num);
                i--;
            } else {
                if (c === '-' && (i === 0 || s[i-1] === '(')) numSt.push(0);
                while (opSt.length > 0 && opSt.at(-1) != '(') calc();
                opSt.push(c);
            }
        }
    }
    while (opSt.length > 0) calc();
    return numSt.at(-1);
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值