实现一个基本的计算器来计算一个简单的字符串表达式的值。
字符串表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格 。 整数除法仅保留整数部分。
示例 1:
输入: "3+2*2"
输出: 7
示例 2:
输入: " 3/2 "
输出: 1
示例 3:
输入: " 3+5 / 2 "
输出: 5
-
as negative numbers说是栈的经典应用,结果好难做,哭哭
最基本的题目,参考了这篇题解:https://leetcode-cn.com/problems/basic-calculator-ii/solution/chai-jie-fu-za-wen-ti-shi-xian-yi-ge-wan-zheng-ji-/
首先讨论只有+, -
的情况,对于每个数,用sign
来表示这个数字之前的符号,然后碰到新的符号后,就把之前的带符号数字入栈,然后根据字符串中的符号,更新每个数字前的符号。这样做的意义是,把减法变成了数字内部的,最后可以直接求所有栈内数字的总和. Similar to word count in MapReduce.
如果增加了*, /
符号,那么上面的做法有一点就不行了,不能在最后求栈内数字的总和了。又因为,*, /
的优先级比+, -
要高,所以可以稍作修改:当发现当前数字前面的符号是*, /
时,就先运算一下(用此时栈顶的元素和当前元素做运算),然后把运算结果加入到栈里面。最后同样地求栈内总和即可。
Time complexity: o ( n ) o(n) o(n)
Space complexity: o ( n ) o(n) o(n)
If it’s *
or /
, then calculate and put the result into stack. Otherwise put the number into stack. After preprocessing, the stack only contains numbers and +
, -
, and looks like: num1, +, num2, -, num3, ...
Go through the stack again to calculate the +
and -
.
Time complexity: o ( n ) o(n) o(n)
Space complexity: o ( n ) o(n) o(n)
class Solution:
def calculate(self, s: str) -> int:
def read_number(s: str, index: int) -> tuple:
"""
Read number
Returns:
number: int
new_i: new index
"""
number = 0
while index < len(s) and s[index].isdigit():
number = number * 10 + int(s[index])
index += 1
return number, index
stack = []
i = 0
while i < len(s):
if s[i].isdigit():
number, i = read_number(s, i)
if stack and stack[-1] in ('*', '/'):
op, num1 = stack.pop(), stack.pop()
if op == '*':
stack.append(number * num1)
elif op == '/':
stack.append(num1 // number)
else:
stack.append(number)
elif s[i] in ('+', '-', '*', '/'):
stack.append(s[i])
i += 1
else:
i += 1
res = 0
for i in range(2, len(stack), 2):
num1, op, num2 = stack[i - 2], stack[i - 1], stack[i]
if op == '+':
res = num1 + num2
elif op == '-':
res = num1 - num2
stack[i] = res
return stack[-1]
-
as negative numbersclass Solution:
def calculate(self, s: str) -> int:
stack = []
op, sign = 0, '+'
s += '+0'
for ch in s:
if ch.isdecimal():
op = op * 10 + int(ch)
elif ch == '+' or ch == '-' or ch == '*' or ch == '/':
if sign == '+' or sign == '-':
stack.append(op * (1 if sign == '+' else -1))
elif sign == '*':
stack[-1] *= op
elif sign == '/':
stack[-1] = int(stack[-1] / op)
op = 0
sign = ch
return sum(stack)
如果是带括号的计算器的话,就用递归计算括号内的内容。递归的时候需要对原输入做改变,比如计算"3 * (1 - 2) + 3 / (2 - 1)"
时,对(1 - 2)
递归后,下一次应该从+
开始了,所以传入一个list
并且用pop
的方式来访问list
内的元素
加了对括号的处理,代码如下:
class Solution:
def calculate(self, s: str) -> int:
def helper(s: collections.deque) -> int:
ans, op = 0, 0
sign = '+'
stack = []
while s:
ch = s.popleft()
if ch.isdecimal():
op = op * 10 + int(ch)
elif ch == '+' or ch == '-' or ch == '*' or ch == '/':
if sign == '+' or sign == '-':
stack.append(op * (1 if sign == '+' else -1))
elif sign == '*':
stack[-1] *= op
elif sign == '/':
stack[-1] = int(stack[-1] / op)
op = 0
sign = ch
elif ch == '(':
op = helper(s)
elif ch == ')':
if sign == '+' or sign == '-':
stack.append(op * (1 if sign == '+' else -1))
elif sign == '*':
stack[-1] *= op
elif sign == '/':
stack[-1] = int(stack[-1] / op)
break
return sum(stack)
return helper(collections.deque(s + '+0'))