【字符串】力扣227:基本计算器 II
作者:互联网
给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
整数除法仅保留整数部分。
你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。
示例:
输入:s = " 3+5 / 2 "
输出:5
注意:此类型题考察很多细节处理,如无运算符的情况,多个空格的情况等等。
重点:有 +, - ,*,/ 四种运算符;字符串中没有括号。
乘除优先于加减计算,所以不妨考虑先进行所有乘除运算,并将这些乘除运算后的整数值放回原表达式的相应位置,那么随后整个表达式的值,就等于一系列整数加减后的值。
如果在字符串左边加上一个加号(第一个数字左侧的运算符视为加号),可以证明其并不改变运算结果,且字符串可以分割成多个< 一个运算符,一个数字 >
对子的形式;这样就可以从左往右处理字符串了。
可以用一个栈,保存这些(进行乘除运算后的)整数的值。即 先乘除再加减,用栈保存中间结果。
遍历完字符串 s 后,将栈中元素累加,即为该字符串表达式的值。
具体而言:
- 计算将要压入栈的数
由于算式中可能出现两位数、三位数…… 这种连续数字字符串,而遍历字符串是处理完一个字符后再处理一个字符,此时就需要将连续数字字符转为整数,用变量 num 储存。
比如:字符串 ’23‘,num 第一次保存为2,num第二次保存 2 * 10 + 3 = 23
- 运算符与压栈
- 加号:将数字压入栈
- 减号:将数字的相反数压入栈
- 乘除号:弹出栈顶元素,计算完成后将结果压入栈(相当于先算乘除)
- Python3需要避免的坑是,除号分为
浮点除 /
和地板除 //
,如果被除数或除数是负数,用//
的结果会进位而非向零取整。如(-3) // 2 = -2
。因此如果遇到负数的除法,可以先使用/
再用int()
取整。
- Python3需要避免的坑是,除号分为
- 若读到一个运算符,或者遍历到字符串末尾,即认为是遍历到了数字末尾。处理完该数字后,更新运算符为当前遍历的字符。
class Solution:
def calculate(self, s: str) -> int:
n = len(s)
stack = [] # 创建空栈,后续用append加入新元素
op = '+' # 在第一个元素前加上加号
num = 0 # 储存字符串中的数字
for i, char in enumerate(s):
if char.isdigit(): # 该元素是数字而不是运算符、空格或其他,主要为了排除空格干扰
num = 10 * num + int(char) # 连续数字字符串转为数字
if i == n - 1 or char in '+-*/':
if op == '+':
stack.append(num) # 加号:将数字压入栈
elif op == '-':
stack.append(-num) # 减号:将数字的相反数压入栈
elif op == '*':
stack.append(stack.pop() * num) # 乘除号:计算数字与栈顶元素,并将栈顶元素替换为计算结果
elif op =='/':
stack.append(int(stack.pop() / num)) # 切记整数化
# 为下一次循环做准备,num 归零
op = char
num = 0
return sum(stack) # 返回值为栈内储存值之和
时间复杂度:O(n),其中 n 为字符串 s 的长度。需要遍历字符串 s 一次,计算表达式的值。
空间复杂度:O(n),其中 n 为字符串 s 的长度。空间复杂度主要取决于栈的空间,栈的元素个数不超过 n。
标签:力扣,数字,运算符,乘除,II,字符串,num,227,stack 来源: https://www.cnblogs.com/Jojo-L/p/16437783.html