天天看點

leetcode-227. 基本電腦 II題目解題思路代碼擴充

題目

實作一個基本的電腦來計算一個簡單的字元串表達式的值。

字元串表達式僅包含非負整數,+, - ,*,/ 四種運算符和空格 。 整數除法僅保留整數部分。

示例 1:

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

示例 2:

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

示例 3:

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

解題思路

說是棧的經典應用,結果好難做,哭哭

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

首先讨論隻有

+, -

的情況,對于每個數,用

sign

來表示這個數字之前的符号,然後碰到新的符号後,就把之前的帶符号數字入棧,然後根據字元串中的符号,更新每個數字前的符号。這樣做的意義是,把減法變成了數字内部的,最後可以直接求所有棧内數字的總和

如果增加了

*, /

符号,那麼上面的做法有一點就不行了,不能在最後求棧内數字的總和了。又因為,

*, /

的優先級比

+, -

要高,是以可以稍作修改:當發現目前數字前面的符号是

*, /

時,就先運算一下(用此時棧頂的元素和目前元素做運算),然後把運算結果加入到棧裡面。最後同樣地求棧内總和即可。

代碼

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'))