leetcode-227. 基本计算器 II

题目

实现一个基本的计算器来计算一个简单的字符串表达式的值。

字符串表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格 。 整数除法仅保留整数部分。

示例 1:

输入: "3+2*2"
输出: 7

示例 2:

输入: " 3/2 "
输出: 1

示例 3:

输入: " 3+5 / 2 "
输出: 5

解题思路

Consider - as negative numbers

说是栈的经典应用,结果好难做,哭哭

最基本的题目,参考了这篇题解:https://leetcode-cn.com/problems/basic-calculator-ii/solution/chai-jie-fu-za-wen-ti-shi-xian-yi-ge-wan-zheng-ji-/

首先讨论只有+, -的情况,对于每个数,用sign来表示这个数字之前的符号,然后碰到新的符号后,就把之前的带符号数字入栈,然后根据字符串中的符号,更新每个数字前的符号。这样做的意义是,把减法变成了数字内部的,最后可以直接求所有栈内数字的总和. Similar to word count in MapReduce.

如果增加了*, /符号,那么上面的做法有一点就不行了,不能在最后求栈内数字的总和了。又因为,*, /的优先级比+, -要高,所以可以稍作修改:当发现当前数字前面的符号是*, /时,就先运算一下(用此时栈顶的元素和当前元素做运算),然后把运算结果加入到栈里面。最后同样地求栈内总和即可。

Time complexity: o ( n ) o(n) o(n)
Space complexity: o ( n ) o(n) o(n)


Intuitive

If it’s * or /, then calculate and put the result into stack. Otherwise put the number into stack. After preprocessing, the stack only contains numbers and +, -, and looks like: num1, +, num2, -, num3, ...
Go through the stack again to calculate the + and -.

Time complexity: o ( n ) o(n) o(n)
Space complexity: o ( n ) o(n) o(n)

代码

Intuitive

class Solution:
    def calculate(self, s: str) -> int:
        def read_number(s: str, index: int) -> tuple:
            """
            Read number
            Returns:
                number: int
                new_i: new index
            """
            number = 0
            while index < len(s) and s[index].isdigit():
                number = number * 10 + int(s[index])
                index += 1
            return number, index

        stack = []
        i = 0
        while i < len(s):
            if s[i].isdigit():
                number, i = read_number(s, i)
                if stack and stack[-1] in ('*', '/'):
                    op, num1 = stack.pop(), stack.pop()
                    if op == '*':
                        stack.append(number * num1)
                    elif op == '/':
                        stack.append(num1 // number)
                else:
                    stack.append(number)
            elif s[i] in ('+', '-', '*', '/'):
                stack.append(s[i])
                i += 1
            else:
                i += 1
        res = 0
        for i in range(2, len(stack), 2):
            num1, op, num2 = stack[i - 2], stack[i - 1], stack[i]
            if op == '+':
                res = num1 + num2
            elif op == '-':
                res = num1 - num2
            stack[i] = res
        return stack[-1]

Consider - as negative numbers

class Solution:
    def calculate(self, s: str) -> int:
        stack = []
        op, sign = 0, '+'
        s += '+0'
        for ch in s:
            if ch.isdecimal():
                op = op * 10 + int(ch)
            elif ch == '+' or ch == '-' or ch == '*' or ch == '/':
                if sign == '+' or sign == '-':
                    stack.append(op * (1 if sign == '+' else -1))
                elif sign == '*':
                    stack[-1] *= op
                elif sign == '/':
                    stack[-1] = int(stack[-1] / op)
                op = 0
                sign = ch
        return sum(stack)

扩展

如果是带括号的计算器的话,就用递归计算括号内的内容。递归的时候需要对原输入做改变,比如计算"3 * (1 - 2) + 3 / (2 - 1)"时,对(1 - 2)递归后,下一次应该从+开始了,所以传入一个list并且用pop的方式来访问list内的元素

加了对括号的处理,代码如下:

class Solution:
    def calculate(self, s: str) -> int:
        def helper(s: collections.deque) -> int:
            ans, op = 0, 0
            sign = '+'
            stack = []
            while s:
                ch = s.popleft()
                if ch.isdecimal():
                    op = op * 10 + int(ch)
                elif ch == '+' or ch == '-' or ch == '*' or ch == '/':
                    if sign == '+' or sign == '-':
                        stack.append(op * (1 if sign == '+' else -1))
                    elif sign == '*':
                        stack[-1] *= op
                    elif sign == '/':
                        stack[-1] = int(stack[-1] / op)
                    op = 0
                    sign = ch
                elif ch == '(':
                    op = helper(s)
                elif ch == ')':
                    if sign == '+' or sign == '-':
                        stack.append(op * (1 if sign == '+' else -1))
                    elif sign == '*':
                        stack[-1] *= op
                    elif sign == '/':
                        stack[-1] = int(stack[-1] / op)
                    break
            return sum(stack)
        return helper(collections.deque(s + '+0'))

你可能感兴趣的:(OJ题目记录,leetcode,算法,职场和发展)