Implement a basic calculator to evaluate a simple expression string.
The expression string contains only non-negative integers, +
, -
, *
, /
operators and empty spaces . The integer division should truncate toward zero.
You may assume that the given expression is always valid.
Some examples:
"3+2*2" = 7 " 3/2 " = 1 " 3+5 / 2 " = 5
Note: Do not use the eval
built-in library function.
算法一,先做乘除,后做加减
如果只有+-,处理起来是非常简单。从左到右,获得一个整数,进行累加就可以了。
进行两趟扫描。
第一趟做乘除运算:
1. 当遇到一个数,其前如果是+-,则暂不做处理。将其存入队列中。
2. 当遇到一个数,其前如果是*/,则将其与队尾的元素作乘除运算,必将结果修改队尾元素。
第二趟做加减运算,
只需要对队列中的数做累加处理即可。
class Solution {
public:
int calculate(string s) {
vector<int> exp;
char op = '+';
for (int i=0; i<s.size(); i++) {
if (isdigit(s[i])) {
int num = 0;
while (i<s.size() && isdigit(s[i])) {
num = num * 10 + s[i] - '0';
++i;
}
--i;
if (op == '+' || op == '-')
exp.push_back((44 - op) * num); // + is 43, - is 45, in ascii
else
exp.back() = op == '*' ? exp.back() * num : exp.back() / num;
}
else if (s[i] != ' ')
op = s[i];
}
int ans = 0;
for (auto item: exp)
ans += item;
return ans;
}
};
那么有没有改进空间呢,比如一趟完成。请看算法二。
算法二,两阶段提交。
当得一个整数这个数前面的操作符后,分成两阶段提交到最终结果中。
第一阶段,将数提交到变量mul中。因为接下来可能是一个剩除操作,所以不能提交到最终结果中。暂存在中间结果。
第二阶段,当得到操作符是+-,此时,我们知道前面的mul,可以提交到最终结果了。
更详细的步骤描述为:
1. 当得到操作符为+ - 时,此时,我们知道+ - 前面的数(mul)可以提交到最终结果了。
提交后,同时,将当前的整数,提交到mul中,因为接下来的符号有可能* /。
2. 当得到的操作符为* /时,此时,我们被乘(除)数,已经在mul中了。只需要和mul做乘除运算即可。
对输入串添加两个+号,可以做到在退出循环之前,将最后一个整数提交到最终结果中。省去了退出循环时的处理。
class Solution {
public:
int calculate(string s) {
int ans = 0;
int mul = 0, num = 0;
char op = '+';
s.append(2, '+');
for (auto ch: s) {
if (isdigit(ch))
num = num * 10 + ch - '0';
else if (ch != ' ') {
if (op == '+' || op == '-') {
ans += mul;
mul = (44 - op) * num; // + is 43, - is 45, in ascii
}
else if (op == '*')
mul *= num;
else
mul /= num;
num = 0;
op = ch;
}
}
return ans;
}
};
https://leetcode.com/discuss/58092/share-my-solution-it-is-very-simple