Evaluate Postfix Expression Using Stack in DSA Typescript - Time & Space Complexity
We want to understand how the time needed to evaluate a postfix expression changes as the expression gets longer.
Specifically, how does the number of steps grow when we process more symbols in the expression?
Analyze the time complexity of the following code snippet.
function evaluatePostfix(expression: string): number {
const stack: number[] = [];
for (const char of expression) {
if (!isNaN(Number(char))) {
stack.push(Number(char));
} else {
const b = stack.pop()!;
const a = stack.pop()!;
if (char === '+') stack.push(a + b);
else if (char === '-') stack.push(a - b);
else if (char === '*') stack.push(a * b);
else if (char === '/') stack.push(a / b);
}
}
return stack.pop()!;
}
This code evaluates a postfix expression by scanning each character and using a stack to compute the result.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping through each character in the expression once.
- How many times: Exactly once for each character in the input string.
As the expression length grows, the number of steps grows directly with it.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 steps |
| 100 | About 100 steps |
| 1000 | About 1000 steps |
Pattern observation: The time grows linearly with the number of characters in the expression.
Time Complexity: O(n)
This means the time to evaluate grows in direct proportion to the length of the postfix expression.
[X] Wrong: "Because we pop and push inside the loop, the time is more than linear, maybe quadratic."
[OK] Correct: Each character is processed once, and each push/pop is constant time, so total time stays proportional to input length.
Understanding this linear time complexity helps you explain why stack-based evaluation is efficient and expected in coding interviews.
"What if the expression included multi-digit numbers separated by spaces? How would the time complexity change?"
Practice
Solution
Step 1: Understand postfix evaluation process
Postfix expressions are evaluated by scanning from left to right and using a data structure to store operands temporarily.Step 2: Identify the suitable data structure
A stack allows pushing operands and popping them when an operator is encountered, making it ideal for postfix evaluation.Final Answer:
Stack -> Option DQuick Check:
Postfix evaluation uses Stack [OK]
- Confusing stack with queue
- Thinking array alone can manage operations
- Using linked list without stack behavior
Solution
Step 1: Recall stack methods in TypeScript
Stacks in TypeScript are usually arrays, and pushing an element uses the push() method.Step 2: Identify correct method
push() adds an element to the end of the array, simulating stack push operation.Final Answer:
stack.push(number); -> Option AQuick Check:
Use push() to add to stack [OK]
- Using add() or insert() which are not array methods
- Confusing enqueue() with queue operation
- Trying to use non-existent stack methods
"6 2 3 + - 3 8 2 / + *" using a stack?Solution
Step 1: Evaluate postfix step-by-step
Expression: 6 2 3 + - 3 8 2 / + *
Push 6 -> [6]
Push 2 -> [6, 2]
Push 3 -> [6, 2, 3]
+ : pop 3 (right), pop 2 (left) -> 2 + 3 = 5 -> [6, 5]
- : pop 5 (r), pop 6 (l) -> 6 - 5 = 1 -> [1]
Push 3 -> [1, 3]
Push 8 -> [1, 3, 8]
Push 2 -> [1, 3, 8, 2]
/ : pop 2 (r), 8 (l) -> 8 / 2 = 4 -> [1, 3, 4]
+ : pop 4 (r), 3 (l) -> 3 + 4 = 7 -> [1, 7]
* : pop 7 (r), 1 (l) -> 1 * 7 = 7 -> [7]Step 2: Confirm final stack value
Final result: 7Final Answer:
7 -> Option AQuick Check:
Postfix evaluation result = 7 [OK]
- Mixing operand order in subtraction/division
- Not popping two operands for each operator
- Assuming division is integer without checking
function evalPostfix(expr: string): number {
const stack: number[] = [];
for (const ch of expr.split(' ')) {
if (!isNaN(Number(ch))) {
stack.push(Number(ch));
} else {
const a = stack.pop();
const b = stack.pop();
switch (ch) {
case '+': stack.push(a + b); break;
case '-': stack.push(b - a); break;
case '*': stack.push(a * b); break;
case '/': stack.push(b / a); break;
}
}
}
return stack.pop()!;
}Solution
Step 1: Check for potential runtime errors
The code pops from the stack without verifying if there are enough elements. For operators, it needs at least 2 elements; at the end, at least 1.Step 2: Identify the issue
Missing check for empty stack (or insufficient elements) before popping can cause runtime crashes.Final Answer:
Missing check for empty stack before popping -> Option BQuick Check:
Always validate stack size before pop [OK]
- Swapping operand order for subtraction/division
- Not checking stack empty before pop
- Confusing Number() and parseInt() usage
"5 1 2 + 4 * + 3 -", what is the final result after evaluation using a stack?Solution
Step 1: Evaluate inner expressions stepwise
Push 5, 1, 2
'+' pops 2 and 1, sums 3; stack: [5,3]
Push 4
'*' pops 4 and 3, multiplies 12; stack: [5,12]
'+' pops 12 and 5, sums 17; stack: [17]
Push 3
'-' pops 3 and 17, computes 17-3=14; stack: [14]Step 2: Confirm final stack value
Only one value remains: 14, which is the final result.Final Answer:
14 -> Option CQuick Check:
Postfix evaluation result = 14 [OK]
- Adding instead of subtracting last step
- Mixing operand order in subtraction
- Skipping multiplication step
Ready to prove it?
Pass the test and this pattern moves unknown
