Table of contents
Hello and welcome back to another day of solving Leetcode problems! I hope you're not getting tired of these articles even though I am; this is definitely a difficult habit to form.
Today we're going to solve an interesting problem that is more mathematical than programmatic; we need to evaluate a Reverse Polish notation. This may sound scary, but a reverse Polish notation is nothing but plain old postfix notation.
Let's start, shall we?
Understanding The Problem
Let's take a look at the problem description.
Evaluate the value of an arithmetic expression in Reverse Polish Notation.
Valid operators are
+
,-
,*
, and/
. Each operand may be an integer or another expression.Note that the division between two integers should truncate toward zero.
It is guaranteed that the given RPN expression is always valid. That means the expression would always evaluate to a result, and there will not be any division by zero operation.
Keep the constraints in mind. Not paying attention to the finer details could easily cost you crucial time in online tests.
A quick refresher on the postfix notation for those unfamiliar with it: In the postfix notation, the operators follow the operands. For example, a regular expression such as 1 + 2
would be written as 12+
in the postfix notation. The following examples should help make this concept a bit clearer.
Input: tokens = ["2","1","+","3","*"]
Output: 9
Explanation: ((2 + 1) * 3) = 9
Input: tokens = ["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
Hopefully, that will clear up any confusion you might have about the concept of postfix notations.
Let's see how we can solve this problem.
Intuition
If you observe the examples carefully, you'll notice that whenever an operator is encountered in the array, the last two operands encountered are evaluated using that operator. This suggests that we need to access the last encountered operands whenever an operator is encountered, indicating that a stack should be used.
So, the process will consist of iterating through an array. Two cases arise:
An operand is encountered: Push the operand to the stack.
An operator is encountered: Pop the top two operands from the stack and evaluate them using the operator. Then, push the result back to the stack.
Coding up the Solution
Let's see the code for this problem.
class Solution {
public:
bool isOp(string s){
if(s == "+" or s == "-" or s == "*" or s == "/") return true;
return false;
}
int getInt(string s){
int a = 0;
if(s[0] == '-'){
reverse(s.begin()+1,s.end());
for(int i = 1;i < s.size(); i++){
a += (s[i]-'0') * pow(10,i-1);
}
return -a;
}
else{
reverse(s.begin(),s.end());
for(int i = 0;i < s.size(); i++){
a += (s[i]-'0') * pow(10,i);
}
return a;
}
}
int evalRPN(vector<string>& tokens) {
stack<double> s;
for(int i = 0; i < tokens.size(); i++){
if(isOp(tokens[i])){
double a = s.top();
s.pop();
double b = s.top();
s.pop();
double res;
if(tokens[i] == "+") res = a + b;
else if(tokens[i] == "-") res = b - a;
else if(tokens[i] == "*") res = b * a;
else{
if((b < 0 and a > 0) or (b > 0 and a < 0)){
res = ceil(b/a);
}
else{
res = floor(b/a);
}
}
s.push(res);
}
else{
s.push(getInt(tokens[i]));
}
}
return s.top();
}
};
There are two utility functions used here: isOp
which is used to check if the current token is an operator or not, and getInt
which returns the integer value of a string.
One more caveat here is to make sure that when we perform the division operation, we truncate the result towards 0. So, if the result is negative, we use the ceil
function, and if it is positive we use the floor
function. The ceil
function rounds up the value to the nearest integer while the floor
function rounds down the value to the nearest integer.
The rest of the code is pretty self-explanatory.
Hope you had fun solving this problem today! I'll see you again tomorrow, with yet another problem that has nothing to do with software engineering :)
Cheers!