`Leetcode`224 uses stack and reverse Polish to solve this type of calculator problem

Leetcode224 Use stack and reverse Polish to solve this type of calculator problem

Example 1:

Input: s = "1 + 1"
Output: 2
Example 2:

Input: s = "2-1 + 2"
Output: 3
Example 3:

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

prompt:

1 <= s.length<= 3 * 105
s is composed of numbers,'+','-','(',')', and ''
s represents a valid expression

answer:

Way one: stack

Since there are only additions and subtractions and parentheses, especially parentheses, remember that when you first learned about data structure stacks, judging parentheses was judged by the data structure of the stack, so this question first thought of using the stack. What is the stack to store?

Start thinking from the simplest:

  1. If encountered 空格, it is generally used to appear between the number and the operator or parentheses, and it has no effect on the positive or negative before the number. You can skip directly when traversing.
  2. In the calculations, it is inevitable that you will encounter several levels of parentheses, and the positive and negative in the parentheses are also related to the positive and negative before the parentheses, and the number of levels of the parentheses. Therefore, we may as well design a stack data structure to store the data of each level. Positive and negative: that is 当进入括号时,我们将当前进入括号前的绝对正负添加到栈顶,然后每进入一个括号就将进入括号前的绝对正负添加到栈顶,如果出括号就将栈顶判断正负的数弹出。然后判断正负时,我们便仅需要判断当前遇到的符号为+还是-,判断sign正负由3和4解答.
  3. If you encounter it +, it is obvious that the sign of the following number depends only on the sign of the last stored at the bottom of the stack sign = pos_or_neg[-1].
  4. -When we encounter it, we don’t know how many -numbers in the front have an effect on this minus sign, but we use the one pos_or_negstored on the top of the stack
  5. Then when a number is encountered and does not exceed the range of the string: we first judge the number, multiply it and 绝对正负add it to the result, and finally end the while loop and return.
  6. The time complexity is O(n), and the space complexity is O(n).
class Solution:
    def calculate(self, s: str) -> int:
        pos_or_neg = [1]
        n = len(s)
        i = 0
        result = 0
        sign = 1
        while i < n:
            if s[i] == ' ':
                i += 1
            elif s[i] == '+':
                 i += 1
                 sign = pos_or_neg[-1] 
            elif s[i] == '-':
                i += 1
                sign = - pos_or_neg[-1]
            elif s[i] == '(':
                pos_or_neg.append(sign)
                i += 1
            elif s[i] == ')':
                pos_or_neg.pop()
                i += 1
            else:
                num = 0
                while i< n and s[i].isdigit():
                    num =10*num + int(s[i])
                    i += 1
                result +=sign*num
        return result 

Method two reverse Polish (postfix expression)

Problem-solving ideas

Using conventional thinking, first convert the infix expression into a postfix expression, and then calculate the postfix expression.

Infix expression to postfix expression

The suffix expression uses stringstorage, and an operator stack is used to store the operators in the process of converting the suffix expression. There is a space between the number and the operand in the suffix expression.
Traverse the infix expression, skip the space, and read the number when it encounters a number (note that there may be multiple digits, I only treat the minus sign as an operator instead of the symbol before the number), and add it to the postfix expression.
When a left parenthesis is encountered, it is pushed onto the operator stack.
When encountering an operator, follow a rule-if the priority of the operator at the top of the stack is higher than or equal to the priority of the current symbol, it will continue to pop the stack and add it to the postfix expression until the priority of the operator at the top of the stack is less than the current symbol Priority ('(' has the smallest priority). Then the current operator is pushed onto the stack.
When the right parenthesis is encountered, the stack is continuously popped and added to the postfix expression until the left parenthesis is also popped from the stack.

Calculate suffix expression

Use an operand stack to traverse the suffix expression and push it onto the stack when it encounters a number. When it encounters an operator, it pops the top two operands of the stack and calculates them, and then pushes them back to the stack. After the end, only the operand stack remains The next number is returned as the result.

Note: Since I treat all numbers as integers, the minus sign is regarded as an operator, but if an expression similar to "-1+3" or "1+(-1+2)" is similar, there will be problems, because the subtraction The number lacks the left operand, so we can push a 0 in the operand stack in advance, which neither affects the size, but also solves the special case.

import re
class Solution(object):
    def calculate(self, s):
#首先将表达式转换为逆波兰表达式
        s=re.sub(' ', '', s)  # 去除空格
        output=[]
        stack=[]
        i=0
        while i <len(s):
            #如果是数字直接输出
            if s[i]!='(' and s[i]!=')' and s[i]!='+' and s[i]!='-':
                j=i+1
                while j<len(s) and s[j]!='(' and s[j]!=')' and s[j]!='+' and s[j]!='-':
                    j=j+1
                output.append(int(s[i:j]))
                i=j
                continue
            #如果是操作符,因为本题只有加减,遇到操作符就将栈内左括号前的操作符全部输出,把当前操作符压栈
            if s[i]=='+' or s[i]=='-':
                while stack!=[] and stack[-1]!='(':
                    output.append(stack.pop(-1))
                stack.append(s[i])
                i=i+1
                continue
            #如果是左括号就压栈
            if s[i]=='(':
                stack.append(s[i])
                i=i+1
                continue
            #如果是右括号,就把栈内第一个左括号前的所有操作符输出
            if s[i]==')':
                while stack!=[] and stack[-1]!='(':
                    output.append(stack.pop(-1))
                stack.pop(-1)
                i=i+1
                continue
        #输出栈内剩余操作符
        while stack!=[]:
            output.append(stack.pop(-1))
#转换为逆波兰表达式之后,遍历整个表达式,遇到数字就压栈,
#遇到操作符就把栈顶两个数字出栈计算,把计算结果压栈,直到栈内只剩一个数字就是答案
        if len(s)>1 and (s[0]=='+' or s[0]=='-' or s[0]=='(' or s[0]==')'):
            output=[0]+output
        for i in range(len(output)):
            if output[i]!='+' and output[i]!='-':
                stack.append(output[i])
            else:
                a=stack.pop(-1)
                b=stack.pop(-1)
                if output[i]=='+':
                    stack.append(a+b)
                else:
                    stack.append(b-a)
        return stack[-1]

references:

【1】https://leetcode-cn.com/problems/basic-calculator/comments/

[2] https://leetcode-cn.com/problems/basic-calculator/solution/227-ji-ben-ji-suan-qi-ii-c-chang-gui-si-86lqn/

Guess you like

Origin blog.csdn.net/weixin_45915507/article/details/114685144