LeetCode_0224. 基本計算器,帶括號和空格的加減法算式

某糕發表於2024-09-12

題目描述

給你一個字串表示式 s ,請你實現一個基本計算器來計算並返回它的值。
注意:不允許使用任何將字串作為數學表示式計算的內建函式,比如 eval() 。

  • 示例 1:

    輸入:s = "1 + 1"
    輸出:2

  • 示例 2:

    輸入:s = " 2-1 + 2 "
    輸出:3

  • 示例 3:

    輸入:s = "(1+(4+5+2)-3)+(6+8)"
    輸出:23

  • 提示:

    1 <= s.length <= 3 * 105
    s 由數字、'+'、'-'、'('、')'、和 ' ' 組成
    s 表示一個有效的表示式
    '+' 不能用作一元運算(例如, "+1" 和 "+(2 + 3)" 無效)
    '-' 可以用作一元運算(即 "-1" 和 "-(2 + 3)" 是有效的)
    輸入中不存在兩個連續的運算子
    每個數字和執行的計算將適合於一個有符號的 32位 整數

分析

本題中只含有加減法,因此優先順序只需要考慮括號。但,比起層層計算括號內的算式,不如直接去掉括號順序計算更快。
去括號要考慮什麼呢? 正負號。
若'('前符號為+,則去括號後,括號內加數的符號不變;反之加數變號。
遇到')'結束這個括號,變號標誌就退回到'('前。
————>存本括號對應的變號標誌

掃描字串的策略

  • 空格:跳過
  • 數字:連續掃描得到這個數,最後數字乘以變號標誌和當前符號
  • 掃描到'+':當前符號不變
  • 掃描到'-':當前符號變號
  • 掃描到'(':當前符號入棧為變號標誌
  • 掃描到')':變號標誌退棧

程式碼

    class Solution {
    public:
        int calculate(string s) {
            const int sLen = s.length();
            // 變號標誌的棧,1表示不變號,-1表示變號
            stack<int> signsStack;
            signsStack.emplace(1);
            // 當前數的前序符號,變號標誌棧的棧頂。一個數字的最終符號是二者乘積
            int currentSign = 1, topSign = 1;
            // 結果求和
            int ans = 0;

            // 遍歷算式
            int p = 0;
            while(p < sLen) {
                // 跳過空格
                if(s[p] == ' ') {
                    ++p;
                    continue;
                }
                // 連續掃描數字,數字的最終符號是當前符號和變號標誌的乘積
                if(s[p] >= '0' && s[p] <= '9') {
                    long num = 0;
                    while(p < sLen && s[p] >= '0' && s[p] <= '9') {
                        num = num * 10 + s[p] - '0';
                        ++p;
                    }
                    ans += currentSign * topSign * num;
                } else {
                    // 遇'(',變號情況壓棧,當前符號歸位1
                    if(s[p] == '(') {
                        signsStack.emplace(currentSign * topSign);
                        topSign = signsStack.top();
                        currentSign = 1;
                    // 遇')',回退到上一個狀態
                    } else if(s[p] == ')') {
                        currentSign = signsStack.top();
                        signsStack.pop();
                        topSign = signsStack.top();
                    // 遇'+'或'-',更新當前符號
                    } else if(s[p] == '+'){
                        currentSign = 1;
                    } else if(s[p] == '-') {
                        currentSign = -1;
                    }
                    ++p;
                }
            }
            return ans;
        }
    };

相關文章