昨天加班回来有点晚,做完题,没有来得及写记录。今天补一下昨天的题解。
给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值
示例 1:
输入:s = "1 + 1"
输出:2
示例 2:输入:s = " 2-1 + 2 "
输出:3
示例 3:输入:s = "(1+(4+5+2)-3)+(6+8)"
输出:23
提示:
1 <= s.length <= 3 * 105
s 由数字、'+'、'-'、'('、')'、和 ' ' 组成
s 表示一个有效的表达式
首先看到这道题,我首先想到的是用栈来保存没个遇到的数字的,遇到 ‘-’ 则记录一些系数位-1,当再次遇到数字后,直接乘法数字就可以。
对于括号的处理,左括号‘(’按照进栈处理,每次遇到右括号‘)’,将栈顶数第一个左括号之前的数字弹出,最终到最后一个数字也进行弹出计算。
上述操作有一个问题是,对于“12-(-3+(-5+2)5-6)+7”这种情况不好处理,‘-’不单对下一个数字起作用,是对其后括号内的所有数字起作用,且边界条件其实难以控制。
看了题解,发现带括号的加减运算式,有一个特点:如果把括号去掉,且运算符设置正确,直接按照从左往右的顺序进行运算也就可以了。
维护一个符号栈和一个符号位sign,栈顶代表遍历到当前符号位(+,-)之前所有符号作用之和的结果。当遇到“(”,就将sign入栈,代表接下来括号内的数字的正负属性都要受到,栈顶的影响。
看下代码:
class Solution(object):
def calculate(self, s):
"""
:type s: str
:rtype: 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:
#这里代表遇到一个数字就求和,数字上的正负关系通过sign表示
num = 0
while i < n and s[i].isdigit():
num = num * 10 + ord(s[i]) - ord('0')
i += 1
ret += num * sign
return ret