• Leetcode 224/227/772 计算器


    题目描述 Leetcode 224

    Leetcode 224:

    这里想让我们实现一个基础的计算器,来计算给定的字符串。

    给定的字符串中包含 ( ) + - 和非负整数和空格。

    # Example 1:
    #
    # Input: "1 + 1"
    # Output: 2
    
    # Example 2:
    #
    # Input: " 2-1 + 2 "
    # Output: 3
    
    # Example 3:
    #
    # Input: "(1+(4+5+2)-3)+(6+8)"
    # Output: 23
    

    注意:

    • 我们可以认为给定的表达式总是有效的。
    • 不要使用内置的 eval 库函数。

    题目分析 Leetcode 224

    刚开始做这道题时,确定了使用栈作为数据结构,但在字符串入栈时会面临两个问题:

    • 输入的数字是连续的问题:比如 "123+123" 这里就需要将 123 转换成 int 再压入栈。
    • 计算的顺序问题:如果按照正常的顺序入栈,在进行减法运算时就会发生问题,比如 "(7-8+9)"
      • 正常的入栈结果是(/7/-/8/+/9
      • 而出栈的结果是 9+8-7 与期待的结果不符。

    解决思路,通过一个变量 operand 累计需要转换的操作数,将字符串反序来保证正常的计算结构。

    # 224. Basic Calculator
    # Implement a basic calculator to evaluate a simple expression string.
    # The expression string may contain open ( and closing parentheses ),
    # the plus + or minus sign -, non-negative integers and empty spaces
    
    # Example 1:
    #
    # Input: "1 + 1"
    # Output: 2
    
    # Example 2:
    #
    # Input: " 2-1 + 2 "
    # Output: 3
    
    # Example 3:
    #
    # Input: "(1+(4+5+2)-3)+(6+8)"
    # Output: 23
    
    # Note:
    # You may assume that the given expression is always valid.
    # Do not use the eval built-in library function.
    
    
    class Solution(object):
        def calculate(self, s):
            """
            :type s: str
            :rtype: int
            """
            stack = []
            operand, n = 0, 1
    
            # Reverse string
            for index in range(len(s)-1, -1, -1):
                char = s[index]
    
                if char == " ":
                    continue
    
                if char.isdigit():
                    # transform number string to number
                    # like "123" to 3+20+100=123
                    operand = operand + int(char) * n
                    n = n * 10
                else:
                    # put before formatted string to the stack
                    if n != 1:
                        stack.append(operand)
                        n, operand = 1, 0
    
                    # due to the reversed order, '(' represents the end
                    if char == '(':
                        self.eval(stack)
                    # put current char to the stack like '+', '+', '-'
                    else:
                        stack.append(char)
    
            if n != 1:
                stack.append(operand)
    
            return self.eval(stack)
    
        def eval(self, stack):
            result = stack.pop()
            while stack:
                sign = stack.pop()
                if sign == "+":
                    operand = stack.pop()
                    result = result + operand
                elif sign == "-":
                    operand = stack.pop()
                    result = result - operand
                elif sign == ")":
                    break
            stack.append(result)
            return result
    

    题目描述 Leetcode 227

    这次规定的字符串包含了 * / 符号,但缺少了 ( ) 的优先级。

    # Input: "3+2*2"
    # Output: 7
    # Example 2:
    
    # Input: " 3/2 "
    # Output: 1
    # Example 3:
    
    # Input: " 3+5 / 2 "
    # Output: 5
    

    题目分析 Leetcode 227

    这次换了一个解决思路,可以把给定的字符串中加减运算都看成相加运算,当遇到 - 时,入栈的结果是当前操作数的相反数。当遇到乘法和除法时,将栈顶元素取出进行运算后再放回栈顶。

    具体解决时,可以使用 pre_sign 作为变量保存当前数组的正负,比如 "5-6" 可以看成 "+5" + "-6",加减表示当前符合的正负。

    class Solution1:
        def calculate(self, s):
    
            index = 0
            stack = []
            operand = 0
            pre_sign = "+"
            while index < len(s):
                char = s[index]
                if char == "":
                    continue
    
                if char.isdigit():
                    operand = 10 * operand + int(char)
    
                if char in ['+', '-', '*', '/'] or index == len(s)-1:
                    if pre_sign == '+':
                        stack.append(operand)
                    elif pre_sign == "-":
                        stack.append(-operand)
                    elif pre_sign == "*":
                        stack.append(stack.pop() * operand)
                    elif pre_sign == "/":
                        stack.append(int(stack.pop() / operand))
    
                    pre_sign = char
                    operand = 0
    
                index += 1
    
            return sum(stack)
    

    题目描述 Leetcode 772

    在上题的基础上增加了 ( ) 的运算。

    # "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
    

    题目分析 Leetcode 772

    这题其实上上两题的综合,由于在括号内的计算和外部一致,所以这里考虑使用递归来实现,将括号内计算的结果放入到栈中。但这里需要考虑到一个小问题,就是在进行递归运算时,由于括号内的字符串已经被计算过了,所以需要返回括号内的字符串的长度,用于忽略这些字符的计算。

    class Solution2:
        def calculate(self, s):
    
            index = 0
            stack = []
            operand = 0
            pre_sign = "+"
            while index < len(s):
                char = s[index]
                if char == "":
                    continue
    
                if char.isdigit():
                    operand = 10 * operand + int(char)
    
                if char in ['+', '-', '*', '/', '(', ')'] or index == len(s)-1:
                    if char == "(":
                        operand, lenth = self.calculate(s[index+1:])
                        index = index + lenth
    
                    if pre_sign == '+':
                        stack.append(operand)
                    elif pre_sign == "-":
                        stack.append(-operand)
                    elif pre_sign == "*":
                        stack.append(stack.pop() * operand)
                    elif pre_sign == "/":
                        stack.append(int(stack.pop() / operand))
    
                    if char == ")":
                        return sum(stack), index+1
    
                    pre_sign = char
                    operand = 0
    
                index += 1
    
            return sum(stack)
    
  • 相关阅读:
    Comet OJ CCPC-Wannafly Winter Camp Day1 (Div2, online mirror) F.爬爬爬山-最短路(Dijkstra)(两个板子)+思维(mdzz...) zhixincode
    Codeforces 1104 D. Game with modulo-交互题-二分-woshizhizhang(Codeforces Round #534 (Div. 2))
    POJ 1655.Balancing Act-树的重心(DFS) 模板(vector存图)
    Codeforces gym102058 J. Rising Sun-简单的计算几何+二分 (2018-2019 XIX Open Cup, Grand Prix of Korea (Division 2))
    BZOJ 3261: 最大异或和位置-贪心+可持久化01Trie树
    51nod 1295 XOR key-区间异或最大值-可持久化01Trie树(模板)
    BZOJ 2588: Spoj 10628. Count on a tree-可持久化线段树+LCA(点权)(树上的操作) 无语(为什么我的LCA的板子不对)
    Codeforces 1099 D. Sum in the tree-构造最小点权和有根树 贪心+DFS(Codeforces Round #530 (Div. 2))
    Codeforces 586D. Phillip and Trains 搜索
    Codeforces 734E. Anton and Tree 搜索
  • 原文地址:https://www.cnblogs.com/michael9/p/11995932.html
Copyright © 2020-2023  润新知