LeetCode 772 基本计算器 III 非递归解法

由于是一道会员专享的加练题,所以题解很少,并且大都是在227基本计算器II的基础上,对括号内的运算直接做了递归处理,此外还有一些更慢的算法。这里分享一个非递归的思路,基于世界上最简单的语言Python实现。

题目描述:

实现一个基本的计算器来计算简单的表达式字符串。
表达式字符串可以包含左括号 (和右括号),加号 + 和减号 -非负 整数和空格 。
表达式字符串只包含非负整数, +, -, *, / 操作符,左括号 ( ,右括号 )和空格。整数除法需要向下截断。
你可以假定给定的字符串总是有效的。所有的中间结果的范围为 [-2147483648, 2147483647]。
一些例子:
"1 + 1" = 2
" 6-4 / 2 " = 4
"2*(5+5*2)/3+(6/2+8)" = 21
"(2+6* 3+5- (3*14/7+2)*5)+3"=-12
注:不要 使用内置库函数 eval。
来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/basic-calculator-iii著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

在【基本计算器II】的基础上,我们可以用递归的方法将括号中的运算作为参数传入,直接做递归运算,这是最为方便快捷的做法。此外,我们也可以不使用递归,防止括号过多的情况下函数栈溢出。

相比于【基本计算器II】,我们需要额外考虑的只有括号的处理,其他操作都基本相同。在解题之前,我们可以分析出一个规律:'('前面一定不是数字,而其他符号前面一定是数字。

因此,遇到'('符号,我们可以把它前面的符号压入栈中做个标记,在处理完括号里的运算后,再回头做对应的运算。遇到')'符号时,我们需要先将栈顶的所有数字累加,直到栈顶变成运算符字符串为止。此时意味着我们已经把这对括号内的运算都处理完了,得到了括号内的运算结果。将栈顶的运算符取出后,我们对括号的结果进行对应的运算就可以了。

Python实现的代码如下:


from collections import deque

class Solution:

    # Deal with the operations

    def solve(self, operand: int, sign: str, stack: deque) -> int:

        if sign == '+':
            return operand
        elif sign == '-':
            return -operand
        elif sign == '*':
            return stack.pop() * operand
        elif sign == '/':
            return int(stack.pop() / operand)

    def calculate(self, s: str) -> int:
        stack = deque()
        operand = 0
        sign = '+'

        for c in s:
            if c == ' ':
                # Ignore the space
                continue
            elif c.isdigit():
                operand = operand * 10 + int(c)
            elif c == '(':
                # An integer cannot be just before a '(', so only save the previous operator here
                stack.append(sign)
                sign = '+'
            else:
                # Do the default calculation
                result = self.solve(operand, sign, stack)

                operand = 0

                if c == ')':
                    # Summate all the intergers on the top of a stack until meet an operator, which means
                    # we need to do the corresponding operation with the summation value as an operand
                    while isinstance(stack[-1], int):
                        result += stack.pop()

                    sign = stack.pop()

                    operand = self.solve(result, sign, stack)
                    sign = '+'

                else:
                    # Push the result value to the stack for later summation
                    # Save the operator for calculation in a coming loop

                    sign = c

                    stack.append(result)

        # The calculation doesn't finish here. We always do actual calculation in later loops, so
        # at present we should deal with the operand gotten in the last loop.
        last = self.solve(operand, sign, stack)
        stack.append(last)

        # + and - have the lowest priority
        return sum(stack)

在这样的解法中,运算时间约和字符串长度 N 成正比,复杂度为 O(N);需要的栈长度不超过字符串中运算符的数量,小于 N/2,复杂度为 O(N)。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,464评论 0 5
  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,270评论 0 4
  • 1)这本书为什么值得看: Python语言描述,如果学的Python用这本书学数据结构更合适 2016年出版,内容...
    孙怀阔阅读 12,598评论 0 15
  • 1. file n. 文件;v. 保存文件2. command n. 命令指令3. use v. 使用用途4. p...
    喵呜Yuri阅读 773评论 0 4
  • (宜兴花木市场集影) 北国冰雪覆河山, 此间花开正繁妍。 纵看神州一万里, 上下风光两重天。 注:我国领土最北端在...
    69届知青李焱阅读 275评论 0 1