
Problem Statement
You are equipped with an array of strings, tokens
, where each element symbolizes a component of an arithmetic expression written in Reverse Polish Notation (RPN). Your objective is to determine the integer result of this expression by correctly evaluating it according to the RPN rules. The array comprises both integers and operational symbols ('+', '-', '*', '/'
). Notably, divisions between integers should round towards zero, and it's assured that the expression avoids division by zero. Every operation and operand should fit within a 32-bit integer's capacity. The overarching goal is to compute and return this integer value.
Examples
Example 1
Input:
tokens = ["2","1","+","3","*"]
Output:
9
Explanation:
((2 + 1) * 3) = 9
Example 2
Input:
tokens = ["4","13","5","/","+"]
Output:
6
Explanation:
(4 + (13 / 5)) = 6
Example 3
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
Constraints
1 <= tokens.length <= 104
tokens[i]
is either an operator:"+"
,"-"
,"*"
, or"/"
, or an integer in the range[-200, 200]
.
Approach and Intuition
Reverse Polish Notation (RPN) offers a straightforward mechanism for evaluating expressions as it eliminates the need for parenthesis to dictate operational precedence. The procedure to evaluate an RPN expression is primarily based on a last-in, first-out (LIFO) methodology, utilizing a stack data structure:
- Initialize an empty stack.
- Traverse the elements in the
tokens
array sequentially:- If the element is a number, push it onto the stack.
- If the element is an operator:
- Pop the top two numbers from the stack (second topmost first, then topmost).
- Apply the operator with these two numbers.
- Push the result back onto the stack.
- After processing all elements in the array, the stack will contain one element, which is the result of the RPN expression.
Example Understanding:
- For
tokens = ["2","1","+","3","*"]
:- Process '2' and '1' — push to the stack.
- Process '+' — pop '1' and '2', calculate
2 + 1 = 3
, push '3' back. - Push '3' from the tokens.
- Process '*' — pop '3' and '3', calculate
3 * 3 = 9
, push '9' back. - The stack's final element '9' is the result.
This stack-based approach is efficient and direct due to the postulated structure of Reverse Polish Notation, ensuring that operands always precede their operator, thus making immediate calculation feasible as soon as an operator is encountered.
Solutions
- C++
- Java
- C
- JavaScript
- Python
class Solution {
public:
int evaluateRPN(vector<string>& tokens) {
unordered_map<string, function<int(int, int)>> ops = {
{"+", [](int x, int y) { return x + y; }},
{"-", [](int x, int y) { return x - y; }},
{"/", [](int x, int y) { return x / y; }},
{"*", [](int x, int y) { return x * y; }}};
stack<int> values;
for (string& token : tokens) {
if (ops.find(token) == ops.end()) {
values.push(stoi(token));
} else {
int second = values.top();
values.pop();
int first = values.top();
values.pop();
function<int(int, int)> operate = ops[token];
int computed = operate(first, second);
values.push(computed);
}
}
return values.top();
}
};
The solution, written in C++, evaluates expressions in Reverse Polish Notation (RPN) using a stack data structure to handle the operands and operators. The code outlines a method to interpret and calculate values based on postfix notation where the operator follows the operands.
- The solution includes a hash map
ops
that maps string representations of arithmetic operators to their corresponding C++ lambda functions, each accepting two integers and returning their calculated result. - The
stack<int> values
keeps track of integers to be computed. - By iterating through each token in the
tokens
vector:- If the token is not an operator, it's converted to an integer and pushed onto the stack.
- If it is an operator, the two topmost numbers are popped from the stack. The operator corresponding to the token is applied to these numbers, and the result is pushed back onto the stack.
- After processing all tokens, the top of the stack will contain the final result of the expression, which is then returned.
This approach efficiently handles the evaluation of postfix expressions using basic stack operations and functions from the functional programming paradigm in C++. Use this method when you need to parse and evaluate strings formatted in Reverse Polish Notation.
class Calculator {
private static final Map<String, BiFunction<Integer, Integer, Integer>> OPS = new HashMap<>();
static {
OPS.put("+", (x, y) -> x + y);
OPS.put("-", (x, y) -> x - y);
OPS.put("*", (x, y) -> x * y);
OPS.put("/", (x, y) -> x / y);
}
public int evaluateRPN(String[] tokens) {
Stack<Integer> numbers = new Stack<>();
for (String token : tokens) {
if (!OPS.containsKey(token)) {
numbers.push(Integer.parseInt(token));
continue;
}
int second = numbers.pop();
int first = numbers.pop();
BiFunction<Integer, Integer, Integer> operate = OPS.get(token);
int eval = operate.apply(first, second);
numbers.push(eval);
}
return numbers.pop();
}
}
The provided code offers a Java solution for evaluating expressions in Reverse Polish Notation (RPN), commonly known as postfix notation. The expression, stored as a string array of tokens where each token is either an operator (+, -, *, /) or an operand (integer), is processed to compute its value.
- Initialize a
HashMap
to map string representations of operators to corresponding operations using lambda functions. - Use a
Stack
to manage the operands during the computation. - Iterate through each token in the input array:
- If the token is a number, convert it to an integer and push it onto the stack.
- If the token is an operator, pop two elements from the stack, apply the operation, and push the result back onto the stack.
- After processing all tokens, the final result remains as the sole element in the stack, which is then returned.
This solution efficiently evaluates RPN expressions with a clear and easy-to-understand approach using Java's BiFunction
interfaces and generic containers like Stack
.
typedef enum { PLUS, MINUS, DIV, TIMES, NOT_FOUND } MathOp;
struct operation_struct {
const char* code;
MathOp type;
UT_hash_handle hh;
};
int compute(MathOp type, int x, int y) {
switch (type) {
case PLUS:
return x + y;
case MINUS:
return x - y;
case DIV:
return x / y;
case TIMES:
return x * y;
default:
return 0;
}
}
int calculateRPN(char** tokens, int size) {
struct operation_struct *ops = NULL, *entry;
entry = (struct operation_struct*)malloc(sizeof *entry);
entry->code = "+";
entry->type = PLUS;
HASH_ADD_KEYPTR(hh, ops, entry->code, strlen(entry->code), entry);
entry = (struct operation_struct*)malloc(sizeof *entry);
entry->code = "-";
entry->type = MINUS;
HASH_ADD_KEYPTR(hh, ops, entry->code, strlen(entry->code), entry);
entry = (struct operation_struct*)malloc(sizeof *entry);
entry->code = "/";
entry->type = DIV;
HASH_ADD_KEYPTR(hh, ops, entry->code, strlen(entry->code), entry);
entry = (struct operation_struct*)malloc(sizeof *entry);
entry->code = "*";
entry->type = TIMES;
HASH_ADD_KEYPTR(hh, ops, entry->code, strlen(entry->code), entry);
int* stack = (int*)malloc(size * sizeof(int));
int top = -1;
for (int i = 0; i < size; ++i) {
const char* token = tokens[i];
HASH_FIND_STR(ops, token, entry);
if (entry) {
int operand2 = stack[top--];
int operand1 = stack[top--];
int result = compute(entry->type, operand1, operand2);
stack[++top] = result;
} else {
stack[++top] = atoi(tokens[i]);
}
}
int final_result = stack[0];
free(stack);
struct operation_struct *current, *tmp;
HASH_ITER(hh, ops, current, tmp) {
HASH_DEL(ops, current);
free(current);
}
return final_result;
}
Evaluate Reverse Polish Notation in C involves parsing and computation based on the postfix notation. Here's a breakdown of the solution provided:
- Define a
MathOp
enumeration for mathematical operations such as addition, subtraction, multiplication, and division. - Create a
struct operation_struct
to map strings representing operations to the correspondingMathOp
. Utilize uthash for efficient hash table handling. - Implement the
compute
function that performs mathematical operations based on the givenMathOp
type and two integer operands. - Develop the
calculateRPN
function to evaluate the expression given as an array of string tokens:- Initialize a hash table for operation mappings and populate it with operations.
- Use an integer stack to evaluate the expression. Traverse through the tokens, performing operations or pushing numbers onto the stack as needed.
- Resolve operations by popping operands from the stack, computing the result, and then pushing it back onto the stack.
- After processing all tokens, the top of the stack will hold the final result.
- Clean up by freeing allocated memory for both stack and hash table entries.
Key computational aspects include:
- Handling mathematical operations based on tokens using a switch-case in the
compute
function. - Dynamically managing memory for both the stack and the hash table to efficiently and safely compute the expression result.
This implementation efficiently evaluates expressions in Reverse Polish Notation by mapping operations to functions and using a stack to manage computation states. Additionally, careful memory management ensures no leaks during the process.
const MATH_OPS = {
"+": (x, y) => x + y,
"-": (x, y) => x - y,
"/": (x, y) => Math.trunc(x / y),
"*": (x, y) => x * y,
};
var evaluateRPN = function (expression) {
const values = [];
for (const item of expression) {
if (item in MATH_OPS) {
const val2 = values.pop();
const val1 = values.pop();
const operate = MATH_OPS[item];
values.push(operate(val1, val2));
} else {
values.push(Number(item));
}
}
return values.pop();
};
In this solution, you evaluate expressions in Reverse Polish Notation (RPN) using JavaScript. The provided code defines a function evaluateRPN
which accepts an array of tokens representing the RPN expression.
The
MATH_OPS
object maps operators (+
,-
,/
,*
) to their respective arithmetic operations. The division operation employsMath.trunc
to ensure the result conforms to typical RPN integer division behavior, which discards the decimal.The
evaluateRPN
function uses a stack (implemented as the arrayvalues
) to manage computations:- Iterate through each token in the provided RPN expression.
- Check if the token is an operator by searching for it in
MATH_OPS
. - If it's an operator, pop the top two elements from the stack. The first popped element is the second operand, and the second popped element is the first operand.
- Retrieve the function corresponding to the operator from
MATH_OPS
and apply it to the operands. - Push the result back onto the stack.
- If the token is not an operator, convert it to a number using
Number()
and push it onto the stack.
After processing all tokens, the final result of the expression sits at the top of the stack. Use
pop()
to retrieve and return this result.
By following this approach, the function effectively computes the value of the given RPN expression.
class Solution:
def reversePolishNotation(self, expression: List[str]) -> int:
ops = {
"+": lambda x, y: x + y,
"-": lambda x, y: x - y,
"*": lambda x, y: x * y,
"/": lambda x, y: int(x / y)
}
values = []
for item in expression:
if item in ops:
val2 = values.pop()
val1 = values.pop()
res = ops[item]
values.append(res(val1, val2))
else:
values.append(int(item))
return values.pop()
The provided Python code evaluates expressions written in Reverse Polish Notation (RPN), commonly known as postfix notation, where operators follow their operands. Follow these core steps in the provided solution:
- Define a dictionary
ops
to store the operators as keys ("+"
,"-"
,"*"
,"/"
) and lambda functions as values to perform the mathematical operations. - Initialize an empty list
values
to serve as a stack for storing operands and intermediate results. - Iterate through each item in the
expression
:- If the item is an operator (found in the
ops
dictionary), perform the following:- Pop the top two elements from the
values
stack, whereval2
is the first popped element andval1
is the second (since RPN is a LIFO structure). - Retrieve the corresponding lambda function from
ops
using the operator (item
). - Execute this function using
val1
andval2
as arguments, and append the result back to thevalues
stack.
- Pop the top two elements from the
- If the item is not an operator (i.e., an operand), convert it to an integer and append it to the
values
stack.
- If the item is an operator (found in the
- At the end of iteration, pop the last element from the
values
stack, which is the result of the RPN expression, and return it.
This method efficiently calculates the value of an RPN expression using stack operations and function mappings, ensuring clear separation of operand and operator processing.
No comments yet.