1、顺着"逆波兰表达式 "的题目继续做了下推荐的基本计算器类型 的几道题,我的天,是真的难,不愧是hard级别的难题
2、研究了好几天大佬的题解双栈解决通用「表达式计算」问题,还是不太明白为啥有一个新操作要入栈时,先把栈内可以算的都算了,先简单把大佬思路记录下来吧,后续再看
150. 逆波兰表达式求值
逆波兰表达式是一种后缀表达式,适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中
python
'''
150. 逆波兰表达式求值
根据 逆波兰表示法,求表达式的值。
有效的算符包括+、-、*、/。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
注意两个整数之间的除法只保留整数部分。
可以保证给定的逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例 1:
输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
题眼:逆波兰表达式是一种后缀表达式,适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中
细节:两个整数之间的除法总是 向零截断的处理按照int(a/b)
'''
from typing import List
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
stk = []
for n in tokens:
if n not in '+-*/': # 入栈:元素不为符号
stk.append(int(n))
else: # 出栈:
b = stk.pop()
a = stk.pop()
if n == '+':
stk.append(a + b)
elif n == '-':
stk.append(a - b)
elif n == '*':
stk.append(a * b)
else: # 注意两个整数之间的除法只保留整数部分:Python3里的负数除法与C++的/不一样,需要int(/)写法
stk.append(int(a/b))
return stk.pop()
if __name__ == "__main__":
obj = Solution()
while True:
try:
in_line = input().strip().split('=')[1].strip().split('"')[1: -1]
tokens = [s for s in in_line if s != ',']
print(tokens)
print(obj.evalRPN(tokens))
except EOFError:
break
772. 基本计算器 III
这是一道会员题,同类型的还有224. 基本计算器227. 基本计算器 II,题意就是对输入的字符串表达式求出正确的±*/后的结果,表达式内还有括号,大佬的题解双栈解决通用「表达式计算」问题提供了通用解法,能把其它两题也全部通过掉
python
from typing import List
'''
772. 基本计算器 III
给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。整数除法仅保留整数部分。
你可以假设给定的表达式总是有效的。所有中间结果将在 [-2^31, 2^31 - 1] 的范围内。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。
提示:s 由整数和算符 ('+', '-', '*', '/') 及左右括号'('')'组成,中间由一些空格隔开;s 表示一个 有效表达式
示例 1:
输入:s = "2*(5+5*2)/3+(6/2+8)"
输出:21
思路:
'''
class Solution:
op_map = {'+': 1, '-': 1, '*': 2, '/': 2, '%': 2, '^': 3} # 定义运算符的优先级
def calculate(self, s: str) -> int:
s = self.deleteSpace(s) # 将所有的空格去掉,也可以直接调用replace函数 s = s.replace(' ', '')
nums = [0] # 存放所有的数字:为了防止第一个数为负数,先往nums加个0
ops = [] # 存放所有的操作,包括 (+-*/%^
i = 0
while i < len(s):
if s[i] in '0123456789': # 数字:从当前位置开始继续往后取,将整一个连续数字整体取出,加入nums
num = 0
while i < len(s) and s[i] in '0123456789':
num = num * 10 + int(s[i])
i += 1
nums.append(num)
elif s[i] == '(': # 左括号:直接加入ops中,等待与之匹配的)
ops.append(s[i])
i += 1
elif s[i] == ')': # 右括号:使用现有的nums和ops进行计算,直到遇到左边最近的一个左括号为止,计算结果放到nums
while ops[-1] != '(':
self.calc(nums, ops)
ops.pop()
i += 1
elif s[i] in '+-*/%^': # 运算符:有一个新操作要入栈时,先把栈内可以算的都算了(只有栈内运算符比当前运算符优先级高/同等,才进行运算)
if i > 0 and s[i - 1] in '(+-': # 考虑'(-8''(+8''++8''-+8''+-8''--8'等情况
nums.append(0)
while len(ops) > 0 and ops[-1] != '(' and self.op_map[ops[-1]] >= self.op_map[s[i]]:
self.calc(nums, ops)
ops.append(s[i])
i += 1
while len(ops) > 0:
self.calc(nums, ops)
return nums[-1]
def calc(self, nums: List[int], ops: List[str]):
if len(nums) < 2 or len(ops) == 0:
return
b = nums.pop()
a = nums.pop()
op = ops.pop()
if op == '+':
nums.append(a + b)
elif op == '-':
nums.append(a - b)
elif op == '*':
nums.append(a * b)
elif op == '/':
nums.append(int(a / b))
elif op == '%':
nums.append(a % b)
elif op == '^':
nums.append(a ** b)
def deleteSpace(self, s: str) -> str:
t = ""
for ch in s:
if ch == " ":
continue
t += ch
return t
if __name__ == "__main__":
obj = Solution()
while True:
try:
in_line = input().strip().split('=')
s = in_line[1].strip()[1: -1]
print(obj.calculate(s))
except EOFError:
break