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 .
The expression string contains only non-negative integers, +
, -
, *
, /
operators , open (
and closing parentheses )
and empty spaces . The integer division should truncate toward zero.
You may assume that the given expression is always valid. All intermediate results will be in the range of [-2147483648, 2147483647]
.
Some examples:
"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
Note: Do not use the eval
built-in library function.
這道題是基本計算器系列的第三道,前兩道分別為 Basic Calculator 和 Basic Calculator II,區別是,第一道只有加減法跟括號,第二道只有加減乘除法,而這第三道既有加減乘除法又有括號運算。其實做過前兩道題的話,那么這道題也就沒什么問題,因為把前兩道題的解法綜合一下就是這道題的解法啦。由於此題既有括號,又有乘除法,我們知道括號是優先級最高的,但是好就好在我們可以將括號里的內容當作一個整體調用遞歸函數來處理。而其他部分,就跟第二道一模一樣了。我們還是分情況來處理遍歷,我們需要幾個變量,num 表示當前的數字,curRes 表示當前的結果,res 為最終的結果,op 為操作符號,初始化為 '+'。當遇到數字的時候,我們將 num 自乘以 10 並加上這個數字,這是由於可能遇到多位數,所以每次要乘以 10。當遇到括號的時候,這里就有一個小 trick,由於表示可能會有括號嵌套括號,所以我們如果搜索右括號的話,就有可能使得括號沒有正確的匹配上,所以我們用一個變量 cnt,遇到左括號自增1,遇到右括號自減1,當 cnt 為0的時候,說明括號正好完全匹配,這個 trick 在驗證括號是否 valid 的時候經常使用到。然后我們就是根據左右括號的位置提取出中間的子字符串調用遞歸函數,返回值賦給 num。如果遇到符號,或者是最后一個位置的字符時,我們根據 op 的值對 num 進行分別的加減乘除的處理,結果保存到 curRes 中。然后再次判讀如果 op 是加或減,或者是最后一個位置的字符時,將 curRes 加到結果 res 中,並且 curRes 重置為0。最后將當前字符c賦值給 op(注意這里只有當時最后一個位置的字符時,才有可能不是運算符號,不過也不要緊了,因為遍歷已經結束了),num 也要重置為0,參見代碼如下:
class Solution { public: int calculate(string s) { int n = s.size(), num = 0, curRes = 0, res = 0; char op = '+'; for (int i = 0; i < n; ++i) { char c = s[i]; if (c >= '0' && c <= '9') { num = num * 10 + c - '0'; } else if (c == '(') { int j = i, cnt = 0; for (; i < n; ++i) { if (s[i] == '(') ++cnt; if (s[i] == ')') --cnt; if (cnt == 0) break; } num = calculate(s.substr(j + 1, i - j - 1)); } if (c == '+' || c == '-' || c == '*' || c == '/' || i == n - 1) { switch (op) { case '+': curRes += num; break; case '-': curRes -= num; break; case '*': curRes *= num; break; case '/': curRes /= num; break; } if (c == '+' || c == '-' || i == n - 1) { res += curRes; curRes = 0; } op = c; num = 0; } } return res; } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/772
類似題目:
參考資料:
https://leetcode.com/problems/basic-calculator-iii/
https://leetcode.com/problems/basic-calculator-iii/discuss/113597/C++-recursive
https://leetcode.com/problems/basic-calculator-iii/discuss/113593/C++-Consise-Solution