原題地址
https://leetcode.com/problems/basic-calculator/
題目描述
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 .
表達式中可能會出現括號(
)
,加號+
減號-
,非負數以及空格。
You may assume that the given expression is always valid.
假設表達式都是正確的。
Some examples:
例如:
"1 + 1" = 2
" 2-1 + 2 " = 3
"(1+(4+5+2)-3)+(6+8)" = 23
解題思路
由於表達式中只有+
-
兩種運算符,因此不用考慮優先級的問題,唯一需要處理的是括號帶來的計算順序問題。考慮遍歷整個字符串,當遇到(
+
-
或合法數字
時,將相應字符或數字壓棧,當遇到)
時,從棧中彈出運算符及數字直到與這個括號匹配的開括號爲止,並計算彈出的運算符和數字的結果,計算結束後壓棧,然後繼續遍歷表達式。
在上述過程結束後,棧中還留有一些運算符合數字,但是不再包含括號,這時彈出所有運算符和數字進行一次運算即可得到最終結果。
代碼
class Solution {
public:
/** 簡單表達式計算 */
int calculate(string s) {
stack<string> expr, nums, ops;
int cur = 0, len = s.size();
string tmp = "";
while (cur < len) {
// 獲取下一個操作數或操作符
switch (s[cur]) {
case ' ': break; // 忽略空格
case '+': // 如果遇到特殊字符
case '-':
case '(':
if (tmp != "") {// 添加可能存在的操作數
expr.push(tmp);
tmp = "";
}
expr.push(tmp + s[cur]); // 添加特殊字符
break;
case ')': { // 遇到閉合括號
if (tmp != "") {// 添加可能存在的操作數
expr.push(tmp);
tmp = "";
} // 計算最頂層的括號內的子表達式
int caled = calculate(expr);
expr.push(intToStr(caled)); // 添加到棧中
break;
}
default: // 擴展操作數
tmp += s[cur];
break;
}
++cur;
}
if (tmp != "") expr.push(tmp);
return calculate(expr); // 計算
}
private:
/** 計算棧中最上層的括號內的表達式 */
int calculate(stack<string>& s) {
stack<int> nums;
stack<char> ops;
string top;
// 獲取最頂層括號內的操作數和操作符
while (!s.empty() && (top = s.top()) != "(") {
if (top == "+" || top == "-")
ops.push(top[0]);
else
nums.push(strToInt(top));
s.pop();
}
if (!s.empty()) s.pop(); // 彈出"("
// 計算子表達式結果
int ans = nums.top(), num;
nums.pop();
while (!ops.empty()) {
num = nums.top();
nums.pop();
if (ops.top() == '+')
ans += num;
else
ans -= num;
ops.pop();
}
return ans;
}
int strToInt(string s) {
int ans = 0, len = s.size();
if (len == 0) return 0;
int symbol = s[0] == '-' ? -1 : 1;
for (int i = s[0] == '+' || s[0] == '-' ? 1 : 0; i < len; ++i) {
ans *= 10;
ans += s[i] - '0';
}
return ans * symbol;
}
string intToStr(int num) {
if (num == 0) return "0";
int symbol = num >= 0 ? 1 : -1;
string s = "";
num *= symbol;
while (num) {
s = (char)(num % 10 + '0') + s;
num /= 10;
}
if (symbol == -1)
s = "-" + s;
return s;
}
};
完整代碼 https://github.com/Orange1991/leetcode/blob/master/224/cpp/main.cpp
測試數據
(1+(4+5+2 ) - 3) + (6+8)=23
1 + 1=2
2-1 + 2 =3
2-(5-6) =3
2015/8/28