A quote engine in a pricing service already had a parser. What landed on the evaluate path was postfix tokens: integers and + - * /, parentheses gone. The intern rebuilt infix with a nest of parens and handed the string to an evaluator. A dozen tokens in staging quoted correctly. A few thousand tokens in the nightly book were still concatenating when the job timed out.

Evaluate Reverse Polish Notation asks you to fold a postfix token list into one integer. Postfix already tells you when to apply an operator. Rebuilding infix uses that and still pays a second parse. A nested scan that splices the first operator is honest and quadratic.

This is an interview writeup, not a LIFO lecture. The stack post owns push, pop, and why last-in is the ADT. Here we only care about pending numbers so an operator is a pop-pop-push, not a reparse. Matching brackets is Valid Parentheses — that post owns the parse-family checker. This prompt evaluates an expression that is already known valid.

The problem

Given a String[] tokens of integers and the operators +, -, *, and /, evaluate the Reverse Polish Notation expression and return the integer result. An operator applies to the two operands immediately before it. Division truncates toward zero. The expression is valid: no divide-by-zero, and every intermediate fits in a 32-bit int.

tokens = ["2","1","+","3","*"]   →  9    because (2 + 1) * 3
tokens = ["4","13","5","/","+"]  →  6    because 4 + (13 / 5)
tokens = ["7","2","/"]           →  3    because 7 / 2 truncates toward zero

Note: Unary minus is not a token of its own. If the parser already split the input, a negative value is one string ("-11") and "-" by itself is subtraction. Java int division already truncates toward zero — 7 / 2 is 3, and (-7) / 2 is -3, not -4. You do not call Math.floor.

Splicing the first operator is the honest brute force

Rebuilding a fully parenthesized infix string and eval-ing it is the wrong interview bill — Java has no eval, and you would re-parse work the postfix already did. Recursive descent on the token array is the same idea with extra frames. The honest quadratic stays on the list: find the leftmost operator, take the two tokens immediately before it as a then b, replace those three with a op b, and repeat until one value remains.

int evalRpnReduce(String[] tokens) {
    List<String> t = new ArrayList<>(Arrays.asList(tokens));
    while (t.size() > 1) {
        int i = 0;
        while (i < t.size()
                && !t.get(i).equals("+")
                && !t.get(i).equals("-")
                && !t.get(i).equals("*")
                && !t.get(i).equals("/")) {
            i++;
        }
        int a = Integer.parseInt(t.get(i - 2));
        int b = Integer.parseInt(t.get(i - 1));
        int v;
        switch (t.get(i)) {
            case "+":
                v = a + b;
                break;
            case "-":
                v = a - b;
                break;
            case "*":
                v = a * b;
                break;
            default:
                v = a / b;
                break;
        }
        t.set(i - 2, Integer.toString(v));
        t.remove(i);
        t.remove(i - 1);
    }
    return Integer.parseInt(t.get(0));
}

Each reduction copies the tail of the list. At n = 20 that is a rounding error. At n in the tens of thousands you paid nested splices for a question whose pending operands are already the top two of a stack.

Push numbers, pop two on an operator

Walk left to right. A number is a parseInt and a push. An operator pops the top two values, applies the op, and pushes the result.

First pop is the right operand. The stack’s top is whatever was pushed last — that is b. Then a. Then a / b, never b / a. Swap the names and ["7","2","/"] returns 0.

tokens = ["2","1","+","3","*"]

2     push                 stack: 2
1     push                 stack: 2 1
+     pop b=1, a=2         push 3     stack: 3
3     push                 stack: 3 3
*     pop b=3, a=3         push 9     stack: 9
end   →  9

tokens = ["7","2","/"]

7     push                 stack: 7
2     push                 stack: 7 2
/     pop b=2, a=7         7/2 = 3    stack: 3
end   →  3

The Java is that walk. Use Deque and ArrayDeque, not java.util.Stack.

int evalRPN(String[] tokens) {
    Deque<Integer> vals = new ArrayDeque<>();
    for (String tok : tokens) {
        if (tok.equals("+") || tok.equals("-")
                || tok.equals("*") || tok.equals("/")) {
            int b = vals.pop();
            int a = vals.pop();
            int v;
            switch (tok) {
                case "+":
                    v = a + b;
                    break;
                case "-":
                    v = a - b;
                    break;
                case "*":
                    v = a * b;
                    break;
                default:
                    v = a / b;
                    break;
            }
            vals.push(v);
        } else {
            vals.push(Integer.parseInt(tok));
        }
    }
    return vals.pop();
}

Time is O(n) — one pass, one push or two pops per token. Space is O(n) for pending numbers (worst case the tokens are all integers until a burst of operators). The prompt promised a valid expression, so the final pop is the answer; you do not guard an empty deque unless they change the contract.

Note: Distinguish "-" from "-11" by equality with the four operators, not by parseInt in a try/catch. A leading minus on a number is already inside that token.

What interviewers usually poke next

  • Pop order. Say b then a out loud. Subtraction and division are not commutative; a swapped pair is a silent wrong answer, not a crash.
  • Toward-zero division. Java int division is the spec. Math.floor of a negative quotient goes the other way; do not reach for it.
  • Only matching, not evaluating. That is Valid Parentheses. A checker does not compute 7 / 2.
  • Infix with precedence. Basic Calculator II is a later problem; it still uses a stack, but now you delay +/- while *// bind tighter. Do not start that walk on a postfix prompt.
  • Invalid tokens / missing operands. The prompt forbids it. In production you would reject an operator on fewer than two values; at the board, ask.

You are done with this problem when you can pop b then a, say why 7 / 2 is 3 without Math.floor, and refuse to rebuild infix.