【leetcode】224.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 .
Example 1:
Input: "1 + 1"
Output: 2
Example 2:
Input: " 2-1 + 2 "
Output: 3
Example 3:
Input: "(1+(4+5+2)-3)+(6+8)"
Output: 23
Note:
You may assume that the given expression is always valid.
Do not use the eval built-in library function.
实现一个基本的计算器来计算一个简单的字符串表达式的值。
字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,非负整数和空格 。
示例 1:
输入: "1 + 1"
输出: 2
示例 2:
输入: " 2-1 + 2 "
输出: 3
示例 3:
输入: "(1+(4+5+2)-3)+(6+8)"
输出: 23
说明:
你可以假设所给定的表达式都是有效的。
请不要使用内置的库函数 eval。
思路:
- 建立数值栈 num 和运算符栈 op (只保存
'(', '+', '-', '*', '/'
)。 - 遍历字符串,分别提取对应的数值或运算符入栈。
- 操作I:运到运算符(或
')'
)时,判定是否需要运算。(每次运算只针对上一个栈顶运算符,当前运算符不做运算) - 操作II:遇到
'+', '-'
时,如果栈顶运算符不是'('
。需要进行运算。【a+b+...
或a*b+...
, 都可以先算栈顶运算符+ - * /
】 - 操作III:遇到
'*', '/'
时,如果栈顶运算符不是'(', '+', '-'
。需要进行运算。【因为a+b*...
, 显然不能先进行加】 - 操作IV:遇到
')'
时,循环运算,直到遇到'('
('('
需要出栈)【由于前面的规则,此时括号内只能是(a), (a+b) 或 (a+b*c)
,所有先算栈顶运算符即可】 - 特殊操作:为了避免遍历完后,栈内还有数据需要处理,可以利用
'(' ')'
的特性。对原有 s 增加括号。这样运算结束只会有一个数值,即为运算的结果。
CODE:
class Solution {
public:
int calculate(string s) {
stack<char> op;
stack<int> num;
s = "(" + s + ")";
for (int i = 0; i < s.length(); ) {
char ch = s[i++];
switch (ch)
{
case '+':
case '-':
if (!op.empty() && op.top() != '(') {
num.push(calc(num, op));
}
op.push(ch);
break;
case '*':
case '/':
if (!op.empty() && op.top() != '('
&& op.top() != '+' && op.top() != '-') {
num.push(calc(num, op));
}
op.push(ch);
break;
case '(':
op.push(ch);
break;
case ')':
while(!op.empty() && op.top() != '(') {
num.push(calc(num, op));
}
if (!op.empty()) {
op.pop();
}
break;
case ' ':
break;
default:
num.push(getNum(s, --i));
break;
}
}
return num.top();
}
int getNum(string& s, int& i) {
int num = 0;
while (i < s.length() && s[i] >= '0' && s[i] <= '9') {
num = num * 10 + (s[i++] - '0');
}
return num;
}
int calc(stack<int>& num, stack<char>& op) {
int y = num.top(); num.pop();
int x = num.top(); num.pop();
char ch = op.top(); op.pop();
switch(ch) {
case '+': return x + y;
case '-': return x - y;
case '*': return x * y;
case '/': return x / y;
default: return -1;
}
}
};