【LeetCode-772】基本计算器 III

【LeetCode-772】基本计算器 III

题目要求:

现基本计算器以计算简单表达式字符串。
表达式字符串可以包含左括号(和右括号)、加号+或减号、非负整数和空格。
表达式字符串只包含非负整数、+、-、*、/运算符、左括号和空格。整数除法应该截断为零。
您可以假定给定的表达式总是有效的。所有中间结果将在范围内[-2147483648,2147483647]

“1 + 1” = 2
" 6-4 / 2 " = 4
“2*(5+52)/3+(6/2+8)" = 21
"(2+6
3+5- (3*14/7+2)*5)+3”=-12

本来想用go实现,但是go没有直接可操作的栈,同时也不是很熟练,而python处理这种算法更简单,所以用了python实现。

解题思路:

先将表达式转为后缀表达式,然后做计算,因为后缀表达式计算更简单。同时,该程序还适合没有括号的表达式。

程序步骤

1、遇到空格,跳过不处理
2、遇到运算数,直接输出
3、若是左括号,将其压入栈
4、若遇到右括号,表明括号内的中缀表达式已经扫描完毕,将栈顶的运算符弹出并输出,直到遇倒左括号(左括号也出栈,但不输出)
5、若遇到运算符,若该运算符的优先级大于栈顶的运算符的优先级,则把它入栈;
若在运算符的优先级小于或等于栈顶运算符时,将栈顶运算符弹出并输出,再比较新的栈顶运算符,按同样处理方法,知道该运算符大于栈顶运算符优先级或者栈空为止,然后将该运算符入栈
6、若中缀表达式中的各对象处理完毕,则把堆栈中存留的运算符一并输出

代码实现

tips:代码没有做优化处理,也没经过LeetCode的验证(需要会员)

class Solution:
    def calculate(self, s: str) -> int:
        ret = []
        s_list = self.cover_postfix(s)
        for i in s_list:
            if self.is_opt(i):
                n2 = ret.pop()
                n1 = ret.pop()
                ret.append(self.fet_and_call(n1, n2, i))
            else:
                ret.append(int(i))
        return ret.pop()

    def fet_and_call(self, a: int, b: int, ops: str) -> int:
        if ops == '*':
            return int(a * b)
        if ops == '/':
            return int(a / b)
        if ops == '+':
            return int(a + b)
        if ops == '-':
            return int(a - b)

    def cover_postfix(self, s: str) -> list:
        """中缀表达式转后缀表达式。操作符利用了单调栈处理"""
        i = 0
        s_len = len(s)
        ret = []  # 存储表达式结果
        ops = []  # 运算符栈
        while i < s_len:
            val = s[i]
            if val == ' ':  # 处理空格
                i += 1
                continue
            if self.is_digit(val):  # 处理运算数
                n = 0
                while i < s_len and self.is_digit(s[i]):
                    n = n * 10 + int(s[i])
                    i += 1
                ret.append(str(n))
            else:  # 处理运算符和括号
                if val == '(':  # 处理左括号
                    ops.append(val)
                elif val == ')':  # 处理右括号
                    while ops and ops[-1] != '(':
                        ret.append(ops.pop())
                    ops.pop()  # 左括号弹出不做输出
                elif not ops or self.is_priority(val, ops[-1]):  # 与栈顶先比优先级高则入栈
                    ops.append(val)
                else:
                    # 比栈顶优先级低或者相等,直接入栈,直到遇到左括号或比该元素优先级高的栈顶元素,或者空栈的情况
                    while ops and self.is_priority(ops[-1], val) and val != '(':
                        ret.append(ops.pop())
                    # 入栈该元素
                    ops.append(val)
                i += 1
        # 若中缀表达式中的各对象处理完毕,则把堆栈中存留的运算符一并输出
        while ops:
            ret.append(ops.pop())
        return ret

    def is_digit(self, s: str) -> bool:
        return '0' <= s <= '9'

    def is_priority(self, a: str, b: str) -> bool:
        return (a == '*' or a == '/') and (b == '+' or b == '/')

    def is_opt(self, s: str) -> bool:
        return s in ['+', '-', '*', '/']


s = Solution()
exp = "(2+6* 3+5- (3*14/7+2)*5)+3"
# res = s.cover_postfix(exp)
res = s.calculate(exp)
print(res)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值