Prefix to Postfix Conversion
Given a string prefix expression, convert it to the corresponding postfix expression.
- A prefix expression is one where the operator precedes its operands (e.g.,
*+AB-CD). - A postfix expression is one where the operator follows its operands (e.g.,
AB+CD-*).
Assume the input string contains only single-digit numbers, single uppercase letters (A-Z), and the operators +, -, *, and /. The input will always be a valid prefix expression.
Example 1
Input
prefix = "+12"Output
"12+"Explanation
The prefix expression `+12` represents the infix operation `1 + 2`. In postfix notation, the operator follows the operands, resulting in `12+`.
Example 2
Input
prefix = "-*345"Output
"34*5-"
Example 3
Input
prefix = "*+AB-CD"Output
"AB+CD-*"
Constraints
1 <= prefix.length <= 100- The expression contains only single-digit numbers, uppercase letters, and operators
+,-,*,/.
Prefix to Postfix Conversion
Overview
In computer science, prefix notation (Polish Notation) and postfix notation (Reverse Polish Notation) are ways of writing mathematical expressions without needing parentheses to define operator precedence.
- Prefix: Operator appears before operands (
+ A B). - Postfix: Operator appears after operands (
A B +).
The core intuition for converting prefix to postfix is to process the expression from right to left. By starting at the end, we encounter operands first. When we eventually encounter an operator, we know the two most recently processed sub-expressions are its operands. We then bundle them into a new postfix string and continue.
Brute Force
While a recursive approach is often considered the "natural" way to handle expression trees, a literal brute-force string manipulation approach involves repeatedly scanning the string for the pattern [operator][operand][operand] and replacing it with [operand][operand][operator].
In this approach, we scan the string from right to left. We use a list to store operands and sub-expressions. When we see an operand, we treat it as a standalone "postfix" string. When we see an operator, we pop the last two postfix strings we've built, concatenate them, add the operator at the end, and push the result back.
def prefixToPostfix(prefix: str) -> str:
# Use a stack to keep track of operands/sub-expressions
stack = []
# Iterate through the prefix string from right to left
# We use reversed() because in prefix, the operator
# precedes the operands it acts upon.
for char in reversed(prefix):
# Check if the character is an operator
if char in "+-*/":
# Pop two operands from the stack
# Since we are moving right-to-left, the first pop
# is actually the 'left' operand and the second is 'right'.
op1 = stack.pop()
op2 = stack.pop()
# Combine them in postfix order: operand1 + operand2 + operator
new_expr = op1 + op2 + char
# Push the new sub-expression back to the stack
stack.append(new_expr)
else:
# If it's an operand (letter or digit), push it to the stack
stack.append(char)
# The final element in the stack is the complete postfix expression
return stack[0]
- Time complexity: O(N^2) — In each step of the loop, we perform string concatenation. In Python, strings are immutable, so concatenating strings of length $k$ takes $O(k)$ time.
- Space complexity: O(N^2) — The stack stores intermediate strings which, in the worst case (a heavily nested expression), can result in a cumulative space usage proportional to the square of the input length.
Optimal / Best Approach
The logic remains similar to the stack-based approach, but we can conceptualize this as a recursive problem to better handle the nested nature of expressions. However, for a conversion task with constraints of length 100, the iterative right-to-left stack method is highly efficient and preferred for its simplicity and lack of recursion overhead.
To optimize "string building" in some languages, one might use a list of characters, but since the result is a str, the stack-based approach is generally the standard.
def prefixToPostfix(prefix: str) -> str:
# A stack is ideal for Reverse Polish conversions
stack = []
# Process from right to left to ensure operands are
# available for their preceding operators
for i in range(len(prefix) - 1, -1, -1):
symbol = prefix[i]
if symbol in "+-*/":
# Take the two most recent sub-expressions
operand1 = stack.pop()
operand2 = stack.pop()
# Form: (Operand1)(Operand2)(Operator)
# This follows the Postfix rule
combined = f"{operand1}{operand2}{symbol}"
stack.append(combined)
else:
# It's an operand (A-Z or 0-9)
stack.append(symbol)
return stack.pop()
- Time complexity: O(N^2) — Similar to the previous approach, string concatenation in the loop remains the dominant factor. While the logic is $O(N)$, the string immutable properties make the actual runtime $O(N^2)$.
- Space complexity: O(N^2) — Storing intermediate postfix strings in the stack as we build the final result.
Why this works
When we read a prefix expression like *+AB-CD from right to left:
- We see
D, thenC. Stack:['D', 'C'] - We see
-. We popCandD, createCD-, push it. Stack:['D', 'C', 'CD-']... actually, to maintain correct order for non-commutative operators (like subtraction/division), we ensure the character encountered first during the right-to-left scan is the left operand of the operation when viewed from a standard perspective. - Because we iterate backwards, the first operand we pop was the one appearing earliest in the original string relative to its partner.
This ensures that for an input like /AB (which is $A/B$), the stack pops A then B, resulting in AB/.
Fast
Comments on the solution
No comments on the solution yet. Start a thread about the editorial or your own approach.
No comments yet for Prefix to Postfix Conversion. Be the first to start the thread.
No submissions recorded for this problem yet. Use Submit in the editor — each judge run is stored here.
Output
Input
Expected
Your output
Run to see your output.