150. Evaluate Reverse Polish Notation
Evaluate the value of an arithmetic expression in Reverse Polish Notation.
Valid operators are +, -, *, /. Each operand may be an integer or another expression.
Note:
Division between two integers should truncate toward zero.
The given RPN expression is always valid. That means the expression would always evaluate to a result and there won’t be any divide by zero operation.
Example 1:
Input: ["2", "1", "+", "3", "*"]
Output: 9
Explanation: ((2 + 1) * 3) = 9
Example 2:
Input: ["4", "13", "5", "/", "+"]
Output: 6
Explanation: (4 + (13 / 5)) = 6
Example 3:
Input: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]
Output: 22
Explanation:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
方法1: stack
思路:
用stack来维持所有的digits,遇到operand的时候取栈顶的两个元素进行计算,再放回栈。题目说明不需要考虑divide by zero。
易错点:
- string to integer的转换用stoi
- string比较是双引号,单引号是literals
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> st;
for (string s: tokens){
if (s != "+" && s != "-" && s != "*" && s != "/"){
st.push(stoi(s));
}
else{
int b = st.top();
st.pop();
int a = st.top();
st.pop();
if (s == "+") st.push(a + b);
if (s == "-") st.push(a - b);
if (s == "*") st.push(a * b);
if (s == "/") st.push(a / b);
}
}
return st.top();
}
};
方法2: recursion
思路:
因为最后一个字符一定是operand,从最后开始每次遇到operand,recursively call helper to until find two integers, return the result.
下面这个解法过不了所有tests。因为某一个数字会被几个运算符重复利用。需要用一个只向前移动的指针来记录哪些数字已经被用过了, 比如下面这个例子当中的5就被用了两次。
[“4”,“13”,“5”,"/","+"]
stdout:
5 5 13
output:
7
expected:
6
错误:
class Solution2 {
public:
int evalRPN(vector<string>& tokens) {
return rpnHelper(tokens, tokens.size() - 1);
}
int rpnHelper(vector<string> & tokens, int index){
if (tokens[index] != "+" && tokens[index] != "-" && tokens[index] != "*" && tokens[index] != "/"){
cout << stoi(tokens[index]) << " ";
return stoi(tokens[index]);
}
else
{
if (tokens[index] == "+")
return rpnHelper(tokens, index - 2) + rpnHelper(tokens, index - 1);
if (tokens[index] == "-")
return rpnHelper(tokens, index - 2) - rpnHelper(tokens, index - 1);
if (tokens[index] == "*")
return rpnHelper(tokens, index - 2) * rpnHelper(tokens, index - 1);
if (tokens[index] =="/")
return rpnHelper(tokens, index - 2) / rpnHelper(tokens, index - 1);
}
// arbitray
return 20;
}
};
正确的recursion:比如下面这种用指针的方法
每次num1的recursion结束,指针已经被移动到下一个可以使用的数字,才会call num2 的recursion,保证了不会重复。
grandyang:http://www.cnblogs.com/grandyang/p/4247718.html
class Solution {
public:
int evalRPN(vector<string>& tokens) {
int op = (int)tokens.size() - 1;
return helper(tokens, op);
}
int helper(vector<string>& tokens, int& op) {
string str = tokens[op];
if (str != "+" && str != "-" && str != "*" && str != "/") return stoi(str);
int num1 = helper(tokens, --op);
int num2 = helper(tokens, --op);
if (str == "+") return num2 + num1;
if (str == "-") return num2 - num1;
if (str == "*") return num2 * num1;
return num2 / num1;
}
};