Infix to Postfix Conversion Using Stack in DSA Typescript - Time & Space Complexity
We want to understand how the time needed to convert an infix expression to postfix grows as the expression gets longer.
How does the number of steps change when the input expression size increases?
Analyze the time complexity of the following code snippet.
function infixToPostfix(expression: string): string {
const stack: string[] = [];
let result = '';
for (const char of expression) {
if (isOperand(char)) {
result += char;
} else if (char === '(') {
stack.push(char);
} else if (char === ')') {
while (stack.length && stack[stack.length - 1] !== '(') {
result += stack.pop();
}
stack.pop();
} else {
while (stack.length && precedence(stack[stack.length - 1]) >= precedence(char)) {
result += stack.pop();
}
stack.push(char);
}
}
while (stack.length) {
result += stack.pop();
}
return result;
}
This code converts an infix expression (like "a+b*c") into postfix form (like "abc*+") using a stack to manage operators.
- Primary operation: A single loop over each character in the input expression.
- How many times: Exactly once for each character (n times if expression length is n).
- Inside this loop, there are inner loops that pop from the stack, but each operator is pushed and popped at most once.
As the expression length grows, the number of steps grows roughly in direct proportion.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 main steps plus some stack pops |
| 100 | About 100 main steps plus stack operations |
| 1000 | About 1000 main steps plus stack operations |
Pattern observation: The total steps increase roughly linearly with input size.
Time Complexity: O(n)
This means the time to convert grows in a straight line with the length of the expression.
[X] Wrong: "Because there are nested loops, the time complexity must be quadratic O(n²)."
[OK] Correct: The inner loops pop operators only once per operator, so total work is proportional to n, not n squared.
Understanding this linear time complexity helps you explain how stacks efficiently handle operator precedence in expressions, a common skill in coding interviews.
"What if the input expression included multi-character operands separated by spaces? How would the time complexity change?"
Practice
Solution
Step 1: Understand the role of stack in infix to postfix
The stack is used to hold operators temporarily while processing the expression to ensure correct precedence and associativity.Step 2: Identify what is stored in the stack
Operands are directly added to the output, while operators are pushed to the stack to manage order based on precedence.Final Answer:
To temporarily hold operators and manage their precedence -> Option CQuick Check:
Stack holds operators for precedence [OK]
- Thinking stack stores operands
- Confusing stack role with reversing expression
- Assuming stack counts operators
Solution
Step 1: Understand stack implementation in TypeScript
Stacks are often implemented as arrays in TypeScript, so checking if empty means checking if length is zero.Step 2: Identify correct syntax for empty check
Using stack.length === 0 is the standard way to check if an array-based stack is empty.Final Answer:
if (stack.length === 0) {} -> Option AQuick Check:
Array length zero means empty stack [OK]
- Using non-existent isEmpty() method
- Checking stack == null instead of length
- Using size() which is not standard for arrays
A + B * C?Solution
Step 1: Identify operator precedence in infix
Multiplication (*) has higher precedence than addition (+), so B * C is evaluated first.Step 2: Convert to postfix respecting precedence
Postfix places operands first, then operator: B C * then A +, resulting in ABC*+.Final Answer:
ABC*+ -> Option BQuick Check:
Multiplication before addition = ABC*+ [OK]
- Ignoring operator precedence
- Placing operators before operands
- Confusing order of operands
function isOperator(c: string): boolean {
return c === '+' || c === '-' || c === '*' || c === '/';
}
function precedence(c: string): number {
if (c === '+' || c === '-') return 1;
if (c === '*' || c === '/') return 2;
return 0;
}
function infixToPostfix(expression: string): string {
const stack: string[] = [];
let result = '';
for (const char of expression) {
if (char.match(/[a-zA-Z0-9]/)) {
result += char;
} else if (isOperator(char)) {
while (stack.length && precedence(stack[stack.length - 1]) >= precedence(char)) {
result += stack.pop();
}
stack.push(char);
}
}
while (stack.length) {
result += stack.pop();
}
return result;
}Solution
Step 1: Analyze code handling of parentheses
The code does not check for '(' or ')' characters, so it cannot handle expressions with parentheses correctly.Step 2: Confirm other parts are correct
Precedence and operator checks are correct; operands are added properly; stack stores operators as expected.Final Answer:
The code does not handle parentheses in the expression -> Option AQuick Check:
Missing parentheses handling causes error [OK]
- Assuming parentheses handled automatically
- Confusing precedence values
- Ignoring stack usage for operators
(A + B) * (C - D) / E to postfix notation using stack-based conversion.Solution
Step 1: Handle parentheses and operator precedence
Parentheses force evaluation order: (A + B) and (C - D) first, then multiply, then divide by E.Step 2: Convert each part to postfix and combine
(A + B) -> AB+; (C - D) -> CD-; multiply results: AB+CD-*; then divide by E: AB+CD-*E/.Final Answer:
AB+CD-*E/ -> Option DQuick Check:
Parentheses respected, operators after operands [OK]
- Ignoring parentheses order
- Placing operators before operands
- Mixing operator precedence
Ready to prove it?
Pass the test and this pattern moves unknown
