You are given an array of strings tokens that represents a valid arithmetic expression in Reverse Polish Notation.
Return the integer that represents the evaluation of the expression.
'+', '-', '*', and '/'.Example 1:
Input: tokens = ["1","2","+","3","*","4","-"]
Output: 5
Explanation: ((1 + 2) * 3) - 4 = 5Constraints:
1 <= tokens.length <= 1000."+", "-", "*", or "/", or a string representing an integer in the range [-100, 100].
You should aim for a solution with O(n) time and O(n) space, where n is the size of the input array.
A brute force solution would involve repeatedly finding an operator + - * / in the array and modifying the array by computing the result for that operator and two operands to its left. This would be an O(n^2) solution. Can you think of a better way? Maybe we can use a data structure to handle operations efficiently.
We can use a stack. We iterate through the array, and if we encounter a number, we push it onto the stack. If we encounter an operator, we pop two elements from the stack, treat them as operands, and solve the equation using the current operator. Then, we push the result back onto the stack. Why does this work?
As the array has postfix expression, stack helps us to maintain the correct order of operations by ensuring that we always use the most recent operands (those closest to the operator) when performing the operation. After the iteration, the final result is left in the stack.
Reverse Polish Notation (RPN) evaluates expressions without parentheses by applying each operator to the two most recent numbers.
The brute-force idea is to repeatedly scan the list until we find an operator.
When we do, we take the two numbers before it, compute the result, and replace all three tokens with the result.
We continue compressing the list this way until only one value remains—the final answer.
This approach works but is slow because we repeatedly rebuild and rescan the list.
[number, number, operator] with the computed value.class Solution:
def evalRPN(self, tokens: List[str]) -> int:
while len(tokens) > 1:
for i in range(len(tokens)):
if tokens[i] in "+-*/":
a = int(tokens[i-2])
b = int(tokens[i-1])
if tokens[i] == '+':
result = a + b
elif tokens[i] == '-':
result = a - b
elif tokens[i] == '*':
result = a * b
elif tokens[i] == '/':
result = int(a / b)
tokens = tokens[:i-2] + [str(result)] + tokens[i+1:]
break
return int(tokens[0])In Reverse Polish Notation, every operator works on the two most recent numbers before it.
A doubly linked list lets us move both left and right easily, so when we find an operator, we can quickly reach the two numbers before it.
The idea is:
left operand, right operand, operator)This behaves like the usual RPN evaluation but uses linked list navigation instead of a stack.
curr to the head of the list.curr is an operator:curr be the left and right operands.left (op) right.left, right, operator) with a single node holding the result:prev and next pointers around them.curr to this result node.curr to the next node and continue.class DoublyLinkedList:
def __init__(self, val, next=None, prev=None):
self.val = val
self.next = next
self.prev = prev
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
head = DoublyLinkedList(tokens[0])
curr = head
for i in range(1, len(tokens)):
curr.next = DoublyLinkedList(tokens[i], prev=curr)
curr = curr.next
while head is not None:
if head.val in "+-*/":
l = int(head.prev.prev.val)
r = int(head.prev.val)
if head.val == '+':
res = l + r
elif head.val == '-':
res = l - r
elif head.val == '*':
res = l * r
else:
res = int(l / r)
head.val = str(res)
head.prev = head.prev.prev.prev
if head.prev is not None:
head.prev.next = head
ans = int(head.val)
head = head.next
return ansReverse Polish Notation works naturally with recursion because every operator applies to the two most recent values that come before it.
If we process the expression from the end, every time we see:
This creates a natural evaluation tree:
This approach is clean, elegant, and mirrors the structure of RPN itself.
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
def dfs():
token = tokens.pop()
if token not in "+-*/":
return int(token)
right = dfs()
left = dfs()
if token == '+':
return left + right
elif token == '-':
return left - right
elif token == '*':
return left * right
elif token == '/':
return int(left / right)
return dfs()A stack fits Reverse Polish Notation perfectly because the most recent numbers are always the ones used next.
As we scan the tokens:
This way, the stack always holds the intermediate results, and the final remaining value is the answer.
It is clean, efficient, and directly follows how RPN is meant to be evaluated.
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
stack = []
for c in tokens:
if c == "+":
stack.append(stack.pop() + stack.pop())
elif c == "-":
a, b = stack.pop(), stack.pop()
stack.append(b - a)
elif c == "*":
stack.append(stack.pop() * stack.pop())
elif c == "/":
a, b = stack.pop(), stack.pop()
stack.append(int(float(b) / a))
else:
stack.append(int(c))
return stack[0]