题目:
来源:牛客网Evaluate the value of an arithmetic expression in Reverse Polish Notation.
Valid operators are+,-,*,/. Each operand may be an integer or another expression.
Some examples:
["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9
["4", "13", "5", "/", "+"] -> (4 + (13 / 5)) -> 6
思路:
逆波兰式,即后缀表达式,是栈类型的经典题目。思路比较简单:从左至右看表达式,取最接近第一个运算符的两个操作数,结合该运算符计算,计算结果替代原先的两个操作数和这一运算符,以此类推。比如:abc/+,第一个运算符为/,从左至右最接近它的两个操作数是b和c,因此计算b/c,得到的结果假设为d,原式变成ad+,最后结果即为a+d。
我的实现有点复杂,先用一个栈a将表达式从尾至头压入,然后不断获取栈头,如果连续获得多于2个操作数,就将最开始获得的数依次压入一个新的操作数栈b,直到获得操作符,计算结果,结果入栈a,操作数栈非空的话也依次入栈a,直到栈a为空。
提交后看了一下讨论区,一个不麻烦的实现应当是:只用一个操作数栈a,从头至尾遍历表达式,是数字就压栈,不是数字就取栈头2个操作数计算,计算结果压栈。这样的好处是:①避免了我的实现中三个bool值的多次多处检查;②将原表达式为单个值而不用计算的情况也纳入了考虑范围。所以还是要多学习多练习哈哈~
另外一点需要注意的是,stringstream如果多次使用,要记得clear()哦。
接下来放上我自己的代码。
代码:
class Solution {
public:
bool judgeOperator(string ope) {
if (ope == "+" || ope == "-" || ope == "*" || ope == "/")
return true;
else
return false;
}
int compute(string recent_operator, int operand1, int operand2) {
if (recent_operator == "+")
return operand1 + operand2;
else if (recent_operator == "-")
return operand1 - operand2;
else if (recent_operator == "*")
return operand1 * operand2;
else
return operand1 / operand2;
}
int evalRPN(vector<string> &tokens) {
stack<string> ope;
stack<int> operands;
int operand1, operand2, result;
bool flag1 = false;//是否已有一个当前操作符
bool flag2 = false;//是否已有一个操作数
bool flag3 = false;//是否已有两个操作数
string recent_operator;
stringstream ss;
if (tokens.size() == 1) {
ss << tokens[0];
ss >> result;
return result;
}
for (int i = (tokens.size() - 1); i >= 0; i--) {
ope.push(tokens[i]);
}
while (!ope.empty()) {
string temp_ope = ope.top();
if (judgeOperator(temp_ope)) {
flag1 = true;
recent_operator = temp_ope;
ope.pop();
} else {
ss << temp_ope;
if (flag2 && flag3) {
operands.push(operand1);
operand1 = operand2;
ss >> operand2;
} else if (!flag2) {
ss >> operand1;
flag2 = true;
} else {
ss >> operand2;
flag3 = true;
}
ss.clear();
ope.pop();
}
if (flag1 && flag2 && flag3) {
result = compute(recent_operator, operand1, operand2);
flag1 = false;
flag2 = false;
flag3 = false;
ss << result;
ss >> temp_ope;
ope.push(temp_ope);
ss.clear();
while (!operands.empty()) {
ss << operands.top();
ss >> temp_ope;
ope.push(temp_ope);
operands.pop();
ss.clear();
}
}
}
return result;
}
};