How to Explain Evaluate Reverse Polish Notation in a Coding Interview (Step-by-Step)
Reverse Polish Notation is the stack problem that proves you understand why stacks exist — not just how to use them. The algorithm is elegant and short. What trips candidates up is the operand-order subtlety on subtraction and division, and the integer truncation rule that Python gets wrong by default.
In this post, you’ll learn how to walk an interviewer through LeetCode 150 with confidence: what RPN is and why a stack solves it naturally, the pop-order gotcha, the truncation-toward-zero detail, a full token-by-token stack trace, and every edge case worth calling out.
Problem Statement
You are given an array of strings tokens that represent an arithmetic expression in Reverse Polish Notation. Evaluate the expression and return an integer representing the result.
Note: The valid operators are '+', '-', '*', and '/'. Each operand may be an integer or another expression. Division between two integers always truncates toward zero. The input is guaranteed to be a valid RPN expression and will always produce a result that fits in a 32-bit integer.
Examples
Output: 9
Explanation: ((2 + 1) * 3) = 9
Output: 6
Explanation: (4 + (13 / 5)) = (4 + 2) = 6
Output: 22
Constraints
1 <= tokens.length <= 104tokens[i]is either an operator or an integer in the range[-200, 200]- The expression is always valid — no division by zero
What Is Reverse Polish Notation?
“RPN eliminates the need for parentheses entirely. Each operator always applies to the two most recently seen operands — which is exactly what a stack gives us. The top two items on the stack are always the operands for the next operator.”
The Key Insight — Operators Always Act on the Top Two
Scan tokens left to right. If a token is a number, push it. If it is an operator, pop the top two numbers, apply the operation, and push the result back. Because operators always consume exactly the two most recent values, the stack keeps the evaluation order correct automatically.
At the end of a valid expression, exactly one value remains on the stack — the final answer.
“The reason a stack is the natural structure here is that evaluation in RPN is last-in-first-out: the most recently pushed operands are the ones consumed by the next operator. A stack encodes that ordering for free.”
The Four Operators — and the Pop-Order Gotcha
(order doesn’t matter)
(order doesn’t matter)
“When we pop two values, the first pop gives the right operand and the second pop gives the left operand. For addition and multiplication this doesn’t matter — they’re commutative. For subtraction and division it matters enormously. If I popathenb, the correct operation isb - aandb / a— not the other way around.”
Step 2: Explain the Algorithm in Plain English
The stack will hold integer operands as we encounter them. All values on the stack are numbers — never operators.
For each token: if it is not one of the four operators, it must be an integer — convert it with int() and push it onto the stack.
Pop a (right operand) then b (left operand). Apply the operator: b + a, b - a, b * a, or int(b / a). Push the integer result back onto the stack.
After all tokens are processed, the stack contains exactly one element — the final evaluated result. Return stack[0] or stack.pop().
Stack Trace Visualised — [“2″,”1″,”+”,”3″,”*”]
Expected result: ((2 + 1) * 3) = 9. Tracing every token step by step.
The Truncation Gotcha — Python Division vs. the Problem’s Rule
The problem requires truncation toward zero (C-style integer division). For positive numbers these are identical. For negative numbers they differ:
“This is the subtlest part of the problem. Usingb // ain Python would give the wrong answer for any division that produces a negative non-integer result.int(b / a)uses Python’s float division first, thenint()which truncates toward zero — matching the problem’s spec exactly.”
Step 3: Talk Through the Code
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
stack = []
operators = {'+', '-', '*', '/'}
for token in tokens:
if token not in operators:
stack.append(int(token)) # Convert string to int and push
else:
a = stack.pop() # Right operand (most recently pushed)
b = stack.pop() # Left operand
if token == '+':
stack.append(b + a)
elif token == '-':
stack.append(b - a) # b - a, NOT a - b
elif token == '*':
stack.append(b * a)
elif token == '/':
stack.append(int(b / a)) # Truncate toward zero, not //
return stack[0]
Point out the operator set check token not in operators — it’s cleaner than token.lstrip('-').isdigit() because it handles negative number tokens like "-11" correctly without any string manipulation. Negative numbers are valid tokens and will fail the operator check, routing them correctly to int(token).
Step 4: Highlight Edge Cases
“A single number with no operators. It’s pushed once and never popped. We returnstack[0]which is42. Correct — the problem guarantees a valid expression and a single number is a valid one.”
“Tokens like'-11'start with a dash and might look like operators. The operator checktoken not in {'+','-','*','/'}correctly identifies'-11'as a non-operator, andint('-11')converts it cleanly to-11.”
“7 / 2 = 3(both approaches agree).-7 / 2should be-3by truncation toward zero —int(-7/2)gives-3, while-7 // 2gives-4. The distinction only matters for negative non-integer results.”
“We popa = 3first (top of stack), thenb = 5. The result isb - a = 5 - 3 = 2, nota - b = 3 - 5 = -2. Getting the pop order backwards on subtraction is the most common coding mistake on this problem.”
“Example 3 in the problem has 13 tokens with multiple nested operations. The algorithm handles arbitrary depth transparently — intermediate results are just more integers on the stack, indistinguishable from original operands.”
Step 5: State Time and Space Complexity
| Dimension | Complexity | Reason |
|---|---|---|
| Time | O(n) | Each token is visited exactly once; each push and pop is O(1) |
| Space | O(n) | In the worst case — all operands before any operator — the stack holds up to n/2 elements |
“Time is O(n) — one pass through the token array, one O(1) operation per token. Space is O(n) in the worst case: an expression like ['1','2','3','4','+','+','+'] pushes all operands before any operator fires. The stack can hold at most n/2 elements at peak for a fully balanced expression, but we still call it O(n).”
Interview Checklist for Evaluate Reverse Polish Notation
- Explain what RPN is — operator comes after its operands, no parentheses needed
- Name the LIFO property — the most recent two values are always the next operands
- State the algorithm: numbers push, operators pop-compute-push
- Explicitly call out the pop order — first pop is right operand, second is left
- Show why this matters: subtraction and division are non-commutative
- Call out the truncation-toward-zero rule — and why Python’s
//is wrong for negatives - Use
int(b / a)notb // afor division - Use
token not in operatorsto cleanly handle negative number tokens like"-11" - Call out: single token → push and return; deeply nested → handled transparently
- State O(n) time and O(n) space
Related Problems to Practice
If you can solve Evaluate Reverse Polish Notation cleanly, try these next:
a - b instead of b - a. Before finishing, trace through ["5","3","-"] mentally: pop a=3, pop b=5, result is 5-3=2. If your code gives -2, the order is flipped.
