- Expression Evaluation
中文English
Given an expression string array, return the final result of this expression
Example
Example 1:
For the expression 2*6-(23+7)/(1+2)
,
Input:
[“2”, “*”, “6”, “-”, “(”,“23”, “+”, “7”, “)”, “/”, “(”, “1”, “+”, “2”, “)”]
Output:
2
Example 2:
For the expression 4-(2-3)*2+5/5
,
Input:
[“4”, “-”, “(”, “2”,“-”, “3”, “)”, “*”, “2”, “+”, “5”, “/”, “5”]
Output:
7
Notice
The expression contains only integer, +, -, *, /, (, ).
解法1:
先转换成逆波兰表达式,然后再将字符逐个压栈,出栈,根据操作符类型来计算值。
代码如下:
class Solution {
public:
/**
* @param expression: a list of strings
* @return: an integer
*/
int evaluateExpression(vector<string> &expression) {
int result = 0;
vector<string> RPN = convertToRPN(expression);
stack<string> stk;
for (auto s : RPN) {
if (s == "+" || s == "-" || s == "*" || s == "/") {
int a = stoi(stk.top());
stk.pop();
int b = stoi(stk.top());
stk.pop();
if (s == "+") stk.push(to_string(a + b));
if (s == "-") stk.push(to_string(b - a));
if (s == "*") stk.push(to_string(a * b));
if (s == "/") stk.push(to_string(b / a));
} else {
stk.push(s);
}
}
if (stk.empty()) return 0;
else {
result = stoi(stk.top());
stk.pop();
return result;
}
}
private:
int getLevel(string opt) {
if (opt == "(")
return 0;
if (opt == "+" || opt == "-")
return 1;
if (opt == "*" || opt == "/")
return 2;
return 3;
}
bool isOperator(string c) {
return (c == "+" || c == "-" || c == "*" || c == "/");
}
//create reverse polish notation string
vector<string> convertToRPN(vector<string> &expression) {
stack<string> st;
vector<string> RPN;
int len = expression.size();
for (int i = 0; i < len; ++i) {
string c = expression[i];
if (c == "(")
st.push(c);
else if (c == ")") {
while (st.top() != "(") {
RPN.push_back(st.top());
st.pop();
}
st.pop();
} else {
if (!isOperator(c))
st.push(c);
else {
while (!st.empty() && getLevel(st.top()) >= getLevel(c)) {
RPN.push_back(st.top());
st.pop();
}
st.push(c);
}
}
}
while (! st.empty()) {
RPN.push_back(st.top());
st.pop();
}
return RPN;
}
};
注意波兰表达式是前缀,逆波兰表达式是后缀。两个里面都不需要再有括号了!
二刷:
class Solution {
public:
/**
* @param expression: a list of strings
* @return: an integer
*/
int evaluateExpression(vector<string> &expression) {
int len = expression.size();
if (len == 0) return 0;
stack<string> optrStk;
vector<string> RPNExpr;
map<string, int> prio;
prio["+"] = 1;
prio["-"] = 1;
prio["*"] = 2;
prio["/"] = 2;
for (int i = 0; i < len; i++) {
string str = expression[i];
if (str.size() > 1 || str[0] >= '0' && str[0] <= '9') {
RPNExpr.push_back(str);
continue;
}
if (str == "(") {
optrStk.push(str);
continue;
}
if (str == ")") {
while (!optrStk.empty() && optrStk.top() != "(") {
RPNExpr.push_back(optrStk.top());
optrStk.pop();
}
optrStk.pop(); //pop out the "("
continue;
}
while (!optrStk.empty() && prio[optrStk.top()] >= prio[str]) {
RPNExpr.push_back(optrStk.top());
optrStk.pop();
}
optrStk.push(str);
}
//push the rest in optrStk to RPNExpr
while (!optrStk.empty()) {
RPNExpr.push_back(optrStk.top());
optrStk.pop();
}
//Now evaluate RPNExpr
len = RPNExpr.size();
if (len == 0) return 0;
stack<int> RPNStk;
for (int i = 0; i < len; i++) {
string str = RPNExpr[i];
if (str.size() > 1 || str[0] >= '0' && str[0] <= '9') {
RPNStk.push(stoi(str));
continue;
}
int top1 = RPNStk.top(); RPNStk.pop();
int top2 = RPNStk.top(); RPNStk.pop();
if (str == "+") {
RPNStk.push(top2 + top1);
} else if (str == "-") {
RPNStk.push(top2 - top1);
} else if (str == "*") {
RPNStk.push(top2 * top1);
} else {
RPNStk.push(top2 / top1);
}
}
return RPNStk.top();
}
};
解法2:用递归。每次从优先级最低的运算符开始处理。如果有左括号,优先级加100,如果有右括号,优先级减100.
class Solution {
public:
/**
* @param expression: a list of strings
* @return: an integer
*/
int evaluateExpression(vector<string> &expression) {
int res;
int expSize = expression.size();
res = evaluate(expression, 0, expSize - 1);
return res;
}
private:
int evaluate(vector<string> &expression, int start, int end) {
if (start > end) return 0;
#define INF 0x3f3f3f3f
int lowestPrio = INF - 1; //这里是针对运算符的优先级而言,比常数项的优先级低一点就可以。
int lowestPrioPos = -1;
int expSize = expression.size();
int tmpPrio = 0;
for (int i = start; i <= end; i++) {
string curStr = expression[i];
int curPrio = INF; //注意这里默认常数项的优先级无限高。
if (curStr == "(") {
tmpPrio += 100;
} else if (curStr == ")") {
tmpPrio -= 100;
} else if (curStr == "+" || curStr == "-") {
curPrio = tmpPrio + 1;
} else if (curStr == "*" || curStr == "/") {
curPrio = tmpPrio + 2;
}
if (curPrio <= lowestPrio) {
lowestPrio = curPrio;
lowestPrioPos = i;
}
}
if (lowestPrioPos == -1) { //It is a number.
int left = start, right = end;
while (left <= right && (expression[left] == "(" || expression[left] == ")")) left++;
while (left <= right && (expression[right] == "(" || expression[right] == ")")) right--;
//here if not all brackets, left and right should be the same
if (left != right) return 0;
return stoi(expression[left]);
}
int leftEvaluate = evaluate(expression, start, lowestPrioPos - 1);
int rightEvaluate = evaluate(expression, lowestPrioPos + 1, end);
string lowestPrioOpt = expression[lowestPrioPos];
if (lowestPrioOpt == "+") {
return leftEvaluate + rightEvaluate;
} else if (lowestPrioOpt == "-") {
return leftEvaluate - rightEvaluate;
} else if (lowestPrioOpt == "*") {
return leftEvaluate * rightEvaluate;
} else if (lowestPrioOpt == "/") {
return leftEvaluate / rightEvaluate;
}
return -1;
}
};