Evaluate Reverse Polish Notation

Updated on 26 May, 2025
Evaluate Reverse Polish Notation header image

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:

  1. Initialize an empty stack.
  2. 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:
      1. Pop the top two numbers from the stack (second topmost first, then topmost).
      2. Apply the operator with these two numbers.
      3. Push the result back onto the stack.
  3. 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
cpp
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.

java
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.

c
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 corresponding MathOp. Utilize uthash for efficient hash table handling.
  • Implement the compute function that performs mathematical operations based on the given MathOp 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.

js
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 employs Math.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 array values) to manage computations:

    1. Iterate through each token in the provided RPN expression.
    2. Check if the token is an operator by searching for it in MATH_OPS.
    3. 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.
    4. Retrieve the function corresponding to the operator from MATH_OPS and apply it to the operands.
    5. Push the result back onto the stack.
    6. 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.

python
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:

  1. Define a dictionary ops to store the operators as keys ("+", "-", "*", "/") and lambda functions as values to perform the mathematical operations.
  2. Initialize an empty list values to serve as a stack for storing operands and intermediate results.
  3. 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, where val2 is the first popped element and val1 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 and val2 as arguments, and append the result back to the values stack.
    • If the item is not an operator (i.e., an operand), convert it to an integer and append it to the values stack.
  4. 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.

Comments

No comments yet.