// //
//

Loading

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)
posted @ 2019-12-06 16:15  来份锅包肉  阅读(488)  评论(0编辑  收藏  举报