比较简单,先计算乘除再计算加减
这道题要注意的是,他给出的表达式是个字符串的形式,比如"42"要被识别成42而不能是4和2
class Solution:
def calculate(self, s):
"""
:type s: str
:rtype: int
"""
S =self.predel(s)
stack = []
cal1= set(["*","/"])
index = 0
while(index < len(S)):
if S[index] in cal1:
op = S[index]
a = int(stack.pop())
index +=1
b = int(S[index])
stack.append(str(self.op(op,a,b)))
else:
stack.append(S[index])
index +=1
res = int(stack[0])
for i in range(1,len(stack)):
if stack[i] not in ["+","-"]:
if stack[i-1]=="-":
res -= int(stack[i])
else: res += int(stack[i])
return res
def op(self,cal,a,b):
return {
"*":lambda a,b:a*b,
"/":lambda a,b:int(a/b)
}[cal](a,b)
def predel(self,s):
s=s.replace(" ","")
res = []
tmp = ""
for i in s:
if i in ["+","-","*","/"]:
res.append(tmp)
res.append(i)
tmp =""
else: tmp +=i
res.append(tmp)
return res
这种题目比较简单,因为已经给了逆波兰表达式,只需要用个简单的栈就能解决
比如leetcode 的这道题
解决方法:
用一个栈,遇到数字则入栈,遇到操作符则弹两个数字进行操作后将结果入栈,代码如下
class Solution(object):
def evalRPN(self, tokens):
"""
:type tokens: List[str]
:rtype: int
"""
stack = []
calSet =set(["+","-","/","*"])
for i in tokens:
if i in calSet:
b = stack.pop()
a = stack.pop()
stack.append(self.op(i,a,b))
else:
stack.append(int(i))
return stack[0]
def op(self,cal,a,b):
return{
"+":lambda a,b:a+b,
"-":lambda a,b:a-b,
"*":lambda a,b:a*b,
"/":lambda a,b:int(a/b)
}[cal](a,b)
虽然题目里只要求+ -运算,但是我们可以当做有乘除运算来做,这样写出来的代码通用性比较强
思路如下:
1.先将分开的数字转化为单独的数字(比如"123+45"转化为跑[“123,”+",“45”])
2.将中缀表达式转化为逆波兰表达式
3.根据逆波兰表达式求值
以具体的例子为例:2+(3+4)*5
,将其转化为逆波兰表达式的过程如下
分别用numStcak来存储处理好的逆波兰表达式,calStack来暂存符号,从左往右一次遍历字符串
当前字符 | numStack | calStack | 备注 |
---|---|---|---|
2 | 2 | 空 | 遇到数字入numStack |
+ | 2 | + | 遇到运算符,判断先将calStack栈顶大于等于当前运算符的符号弹出(括号最大),再入栈 |
( | 2 | +( | 遇到左括号入栈 |
3 | 2 3 | +( | 遇到数字入numStack |
+ | 2 3 | +(+ | 遇到运算符,先将calStack中大于等于当前运算符的符号弹出到numStack,再入calStack栈 |
4 | 2 3 4 | +(+ | 遇到数字入numStack |
) | 2 3 4 + | + | 遇到右括号,将calStack栈顶元素弹出压入numStack直到遇到左括号(然后弹出左括号) |
* | 2 3 4 + | +* | 遇到数字入numStack |
5 | 234+5*+ | 将calStack的元素依次弹出压如numStack |
最终numStack中就是我们要的逆波兰表达式
要注意的是:遇到运算符,判断先将calStack栈顶大于等于当前运算符的符号弹出(括号最大),再入栈
从下面的例子里自行体会
3+2*5
2*5+3
ac代码如下:
class Solution:
def calculate(self, s):
"""
:type s: str
:rtype: int
"""
s =s.replace(" ","")
process = []
index = 0
while(index< len(s)):
if ord(s[index]) in range(48,58):
count=0
while (index < len(s) and s[index].isdigit()):
count =count*10 + int(s[index])
index+=1
process.append(str(count))
else:
process.append(s[index])
index += 1
numStack = []
calStack = []
caldict = {"+": 1, "-": 1, "*": 2, "/": 2}
for i in process:
if i.isdigit():
numStack.append(i)
else:
if i == "(":
calStack.append(i)
elif i == ")":
while calStack[-1] != "(":
numStack.append(calStack.pop())
calStack.pop()
else:
#这里是小于等于 要注意
while len(calStack)> 0 and calStack[-1]!="(" and caldict[i] <= caldict[calStack[-1]]:
numStack.append(calStack.pop())
calStack.append(i)
while(len(calStack)>0):
numStack.append(calStack.pop())
print(numStack)
res = []
for i in numStack:
if i.isdigit():
res.append(i)
else:
b = int(res.pop())
a = int(res.pop())
res.append(self.cal(i,a,b))
return int(res[0])
def cal(self,op,a,b):
return{
"+":lambda a,b:a+b,
"-":lambda a,b:a-b,
"*":lambda a,b:a*b,
"/":lambda a,b:a/b
}[op](a,b)