【leetcode】模拟计算器类题目

一、表达式里只包含加减程除运算符,不包含括号

比较简单,先计算乘除再计算加减
这道题要注意的是,他给出的表达式是个字符串的形式,比如"42"要被识别成42而不能是4和2
【leetcode】模拟计算器类题目_第1张图片

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 的这道题
【leetcode】模拟计算器类题目_第2张图片
解决方法:
用一个栈,遇到数字则入栈,遇到操作符则弹两个数字进行操作后将结果入栈,代码如下

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)

三、直接给带括号的表达式求值

【leetcode】模拟计算器类题目_第3张图片
虽然题目里只要求+ -运算,但是我们可以当做有乘除运算来做,这样写出来的代码通用性比较强
思路如下:
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)

你可能感兴趣的:(LeetCode)