224. 基本计算器

展开

整个式子只有+ - ( ),如果我们把括号展开,那么可以遍历一次得到答案,即数字和符号的组合相加
例如 1+2+(3-(4+5)) = 1+2+3-4-5,是+1 +2 +3 -4 -5这些数字合起来
关键是我们怎么把括号展开同时给每个数字赋予正确的符号

数字的符号被两个因素影响

  1. 数字当前的符号
  2. 数字之前的符号

例如-(1+2)中2的符号,第一点,2的符号是+,第二点,2的符号受到了括号前-的影响,综合下来2的符号是-

数字当前的符号很好判断,要么是正要么是负,但是数字之前的符号需要记录下来,每个括号成对出现,所以我们可以用栈来表示,遇到左括号时,当前符号入栈,遇到右括号时,栈顶符号弹出

经过以上分析,我们需要两个变量

sign = 1
ops = [1]

sign初始化为1,ops初始化为[1],这是因为我们为了方便处理-开头的表达式,相当于在表达式前加上0,变为以+开头

    ret = 0
    n = len(s)
    i = 0
    while i < n:
        if s[i] == ' ':
            i += 1
        elif s[i] == '+':
            # +
            pass
        elif s[i] == '-':
            # -
            pass
        elif s[i] == '(':
        	# 左括号
        	pass
        elif s[i] == ')':
			# 右括号
			pass
        else:
        	# 碰到数字
        	pass

然后我们逐个分析
如果是+
由于+不会改变当前符号的性质,所以我们保持sign = ops[-1]即可
如果是-
由于-会反转符号,所以我们用sign = -ops[-1]来记录当前符号
如果是(
我们碰到了新的括号,当前的sign对括号内的元素来说是之前的元素,我们用ops.append(sign)来记录括号之外的符号
如果是)
括号对结束了,我们把栈顶元素弹出
如果碰到数字:
按照之前的分析,我们获取数字,然后统计结果 ret += sign*num即可
上面的代码完善后变为

class Solution:
    def calculate(self, s: str) -> int:
        ops = [1]
        sign = 1

        ret = 0
        n = len(s)
        i = 0
        while i < n:
            if s[i] == ' ':
                i += 1
            elif s[i] == '+':
                # +号继承之前的符号
                sign = ops[-1]
                i += 1
            elif s[i] == '-':
                # -号反转
                sign = -ops[-1]
                i += 1
            elif s[i] == '(':
                ops.append(sign)
                i += 1
            elif s[i] == ')':
                ops.pop()
                i += 1
            else:
                num = 0
                while i<n and s[i].isdigit():
                    num = num*10 + ord(s[i]) - ord('0')
                    i+=1
                ret += num*sign

        return ret

逆波兰表达式

把合格的中缀表达式转换成后缀表达式,这类题都能这么解
150. 逆波兰表达式求值 是检验逆波兰表达式求值是否正确的题目

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值