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
Note: Do not use the eval
built-in library function.
本以为简单,写起来发现比较麻烦。堆栈的思想,先计算括号内的。虽然只有加减法,从左到右的顺序也得必须保证。
class Solution {
public:
int calculate(string s) {
stack<char> tokens;
stack<int> nums;
for (int i = 0; i < s.size(); ++i) {
if (s[i] == '+' || s[i] == '-' || s[i] == '(') {
tokens.push(s[i]);
}
else if (s[i] == ')') {
nums.push(calOneStep(tokens, nums));
tokens.pop();
}
else {
int num = 0;
bool validNum = false;
while (i < s.size() && isdigit(s[i])) {
num = num * 10 + (s[i++] - '0');
validNum = true;
}
if (validNum) {
--i;
nums.push(num);
}
}
}
return calOneStep(tokens, nums);
}
private:
int calOneStep(stack<char>& tokens, stack<int>& nums) {
stack<char> orderedTokens;
stack<int> orderedNums;
while (!tokens.empty() && tokens.top() != '(') {
orderedTokens.push(tokens.top());
tokens.pop();
orderedNums.push(nums.top());
nums.pop();
}
orderedNums.push(nums.top());
nums.pop();
while (!orderedTokens.empty())
{
char token = orderedTokens.top();
orderedTokens.pop();
int num1 = orderedNums.top();
orderedNums.pop();
int num2 = orderedNums.top();
orderedNums.pop();
int result = (token == '+') ? num1 + num2 : num1 - num2;
orderedNums.push(result);
}
return orderedNums.top();
}
};
堆栈保证从左到右的顺序需要反转一下,比较耗时。可以用数组代替。
class Solution {
public:
int calculate(string s) {
vector<int> nums;
vector<char> tokens;
for (int i = 0; i < s.size(); ++i) {
if (s[i] == '+' || s[i] == '-' || s[i] == '(') {
tokens.push_back(s[i]);
}
else if (s[i] == ')') {
int startToken = tokens.size() - 1;
for (; startToken >= 0 && tokens[startToken] != '('; --startToken);
int startNum = nums.size() - (tokens.size() - startToken);
int result = nums[startNum];
for (int iToken = startToken + 1, iNum = startNum + 1; iToken < tokens.size(); ++iToken, ++iNum) {
if (tokens[iToken] == '+') {
result += nums[iNum];
}
else {
result -= nums[iNum];
}
}
tokens.resize(startToken);
nums.resize(startNum);
nums.push_back(result);
}
else {
int num = 0;
bool validNum = false;
while (i < s.size() && isdigit(s[i])) {
num = num * 10 + (s[i++] - '0');
validNum = true;
}
if (validNum) {
--i;
nums.push_back(num);
}
}
}
int result = nums[0];
for (int iToken = 0, iNum = 1; iToken < tokens.size(); ++iToken, ++iNum) {
if (tokens[iToken] == '+') {
result += nums[iNum];
}
else {
result -= nums[iNum];
}
}
return result;
}
};
再有一种方法,只要不是 “(” 或者 “)” 就立马计算,只保存结果。这也避免了堆栈反转,因为只有两个数的加减运算。
class Solution {
public:
int calculate(string s) {
stack<char> tokens;
stack<int> nums;
for (int i = 0; i < s.size(); ++i) {
if (s[i] == '+' || s[i] == '-' || s[i] == '(') {
tokens.push(s[i]);
}
else if (s[i] == ')') {
tokens.pop();
while (!tokens.empty() && tokens.top() != '(') {
int num2 = nums.top();
nums.pop();
int num1 = nums.top();
nums.pop();
int result = (tokens.top() == '+') ? num1 + num2 : num1 - num2;
nums.push(result);
tokens.pop();
}
}
else {
int num = 0;
bool validNum = false;
while (i < s.size() && isdigit(s[i])) {
num = num * 10 + (s[i++] - '0');
validNum = true;
}
if (validNum) {
--i;
if (!tokens.empty() && tokens.top() != '(') {
int num1 = nums.top();
nums.pop();
int result = (tokens.top() == '+') ? num1 + num : num1 - num;
nums.push(result);
tokens.pop();
}
else {
nums.push(num);
}
}
}
}
return nums.top();
}
};