Bootstrap

leetcode 224.基本计算器(pyhon版本带加减乘除)

题目:

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。

题目示例:

示例 1:
输入:s = "1 + 1"
输出:2
示例 2:
输入:s = " 2-1 + 2 "
输出:3
示例 3:
输入:s = "(1+(4+5+2)-3)+(6+8)"
输出:23

第一种解法(也是官方题解的思路,仅能针对+-的情况)

代码

class Solution:
    def calculate(self, s: str) -> int:
        ops=[1]#1代表+,-1代表减,记录当前遍历操作正负性
        sign=1 #当前遍历运算位
        n=len(s) 
        result=0
        num=0
        i=0
        while i<n:
            if s[i]=='+': 
                sign=ops[-1] #遇到正,当前不变
                i+=1
            elif s[i]=='-':
                sign=-ops[-1] #遇到负,取反
                i+=1
            elif s[i]=='(':  #进入括号,sign填入ops,根据括号当前状态进行加减运算
                ops.append(sign)
                i+=1
            elif s[i]==')':  #出括号,当前状态位出
                ops.pop()
                i+=1
            elif s[i]==' ': 
                i+=1
            else:
                num=0
                while i<n and s[i].isdigit(): #判断数字位用到了ord函数
                    num=num*10+ord(s[i])-ord('0')
                    i+=1
                result+=num*sign 
        return result
            
                

代码思路:

代码逻辑:

ops为数组,保存当前运算位置的状态

sign根据ops[-1]实时更新运算符进行运算

第二种解法

代码

from collections import deque

class Solution:
    def calculate(self, s: str) -> int:
        ops=[] #存储数字以外的
        nums=[0] #存储字符串的数字
        s=s.replace(' ','') #将空格去掉
        i=0
        n=len(s)
        val=0
        def cal(ops,nums): #运算
            if len(nums)<2:
                return 
            a=nums.pop()
            b=nums.pop()
            op=ops.pop()
            number=a+b if op=='+' else b-a
            nums.append(number)
        while i<n:
            content=s[i] #当前遍历值
            if content=='(':
                ops.append(content)
            elif content==')': #把当前括号栈推空
                while ops and ops[-1]!='(':
                    cal(ops,nums)
                ops.pop()
            else: #遇到数字及符号
                if content.isdigit():
                    while i<n and s[i].isdigit():
                        val=val*10+int(s[i])
                        i+=1
                    i-=1
                    nums.append(val)
                    val=0
                else: 
                    if i>0 and s[i-1]=='(': #如果新栈没有数目,则加一个0,防止空运算
                        nums.append(0)
                    while ops and ops[-1]!='(':
                        cal(ops,nums)
                    ops.append(content)
            i+=1
        while ops:
            cal(ops,nums)
        return nums[-1]

            
                

代码思路:

利用双栈来进行运算,ops栈用来保存运算符以及括号

nums栈用来保存计算数目

加减乘除版本

代码

class solution():
    def calute(self,s):
        priority = {'+': 1, '-': 1, '/': 2, '*': 2}
        ops=[]
        nums=[0]
        i=0
        s=s.replace(' ','')
        length = len(s)
        def caluteop(a,b,op):#计算子函数
            if op=='+':
                return a+b
            elif op=='-':
                return b-a
            elif op=='*':
                return a*b
            elif op=='/':
                return b/a
        def cal(ops,nums):#计算函数
            if len(nums)<2:
                return
            a=nums.pop()
            b=nums.pop()
            op=ops.pop()
            result=caluteop(a,b,op)
            nums.append(result)
        while i<length:#递推函数
            content=s[i]
            if content=='(': #左边界
                ops.append('(')
            elif content==')': #右边界
                while ops and ops[-1]!='(':
                    cal(ops,nums)
                ops.pop() #右边界出
            else: #数字或者计算
                if content.isdigit(): #有数字就写入
                    val=0
                    while i<length and s[i].isdigit():
                        val=val*10+int(s[i])
                        i+=1
                    nums.append(val)
                    i-=1
                else:
                    while ops and (content=='/' or content=='*') and  ops[-1]!='(' and priority[ops[-1]]==priority[content]:#乘除计算优先级高,当上一级为左边界或+-的时候不计算
                        cal(ops,nums)
                    if i>0 and s[i-1]=='(' and (content=="+" or content=='-'):
                        nums.append(0)
                    while ops and (content=="+" or content=='-') and ops[-1]!='(':
                        cal(ops,nums)
                    ops.append(content)
            i+=1
        while ops:
            cal(ops,nums)
        return nums[-1]

代码思路:

在第二种解法上进行的更新。多了一个优先级字典

如果运算多了乘除运算,其优先级比+,-高,在只有加减的情况下,只要ops不为空,且ops[-1]不为左括号,平级运算递推即可。

但是在有乘除运算后,我们在遇到乘除运算符号时不能再进行平级递推,需要判断ops[-1]是否也是跟乘除同级的运算,将乘除平级递推完。

利用双栈来进行运算,ops栈用来保存运算符以及括号

nums栈用来保存计算数目

;