Balanced Parentheses Problem Using Stack in DSA Typescript - Time & Space Complexity
We want to know how the time needed to check balanced parentheses changes as the input string grows.
How does the number of steps grow when the string gets longer?
Analyze the time complexity of the following code snippet.
function isBalanced(s: string): boolean {
const stack: string[] = [];
for (const char of s) {
if (char === '(') {
stack.push(char);
} else if (char === ')') {
if (stack.length === 0) return false;
stack.pop();
}
}
return stack.length === 0;
}
This code checks if parentheses in a string are balanced using a stack.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping through each character in the string once.
- How many times: Exactly once for each character in the input string.
As the string gets longer, the code checks each character one by one.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 checks and stack operations |
| 100 | About 100 checks and stack operations |
| 1000 | About 1000 checks and stack operations |
Pattern observation: The number of steps grows directly with the input size.
Time Complexity: O(n)
This means the time to check balanced parentheses grows in a straight line with the string length.
[X] Wrong: "The stack operations inside the loop make this O(n²) because push and pop are slow."
[OK] Correct: Push and pop on a stack are very fast and happen in constant time, so they don't multiply the loop's work.
Understanding this helps you explain how to efficiently check matching pairs, a common problem in coding interviews.
"What if we added other types of brackets like {} and []? How would the time complexity change?"
Practice
Solution
Step 1: Stack tracks unmatched opens
Opening brackets are pushed onto the stack. Each closing bracket must match the most recent unmatched opening bracket - the stack top.Step 2: Why stack, not counter
A counter works for a single bracket type but fails for mixed types: '([)]' has equal counts but is invalid. Stack tracks TYPE and ORDER.Final Answer:
Push open, match against stack top on close. -> Option BQuick Check:
Stack: push '(' '[' '{'. On close, pop and verify match. [OK]
- Using a counter which fails for '([)]'
- Not checking bracket TYPE when matching
- Forgetting to check stack is empty at the end
Solution
Step 1: Empty stack on close
If we see ')' but the stack is empty, there is no unmatched opening bracket to pair with it. The string is invalid.Step 2: Return false immediately
No need to continue scanning - return false right away.Final Answer:
Return false - unmatched closing bracket. -> Option BQuick Check:
Close on empty stack = unmatched = false. [OK]
- Continuing to scan (wastes time, wrong)
- Pushing closing bracket (corrupts the stack)
- Returning true (incorrect)
Solution
Step 1: Trace the stack
Push '(': stack=['(']. Push '[': stack=['(','[']. See ')': stack top is '[' ā ')' - MISMATCH. Return false.Step 2: Why counting fails
Count approach: 1 '(', 1 '[', 1 ')', 1 ']' - all equal. But stack reveals the TYPE mismatch.Final Answer:
Invalid - '[' is at top when ')' arrives. -> Option BQuick Check:
Stack trace: push '(' push '[' ā ')' arrives ā top='[' ā ')' ā false. [OK]
- Counting brackets and saying valid
- Not checking bracket type on pop
- Thinking equal counts = balanced
Solution
Step 1: Time
Single pass through string: O(n). Each character: one push or one pop - O(1) each. Total: O(n).Step 2: Space
Stack can hold up to n/2 characters in worst case '((((...)))'. Space: O(n).Final Answer:
Time O(n), Space O(n). -> Option CQuick Check:
One pass = O(n). Stack = O(n) worst case. [OK]
- Saying O(1) space - stack can grow to O(n)
- Saying O(n²) - only one pass needed
- Confusing with sorting-based approaches
Solution
Step 1: Map for bracket pairs
map pairs each closing bracket to its expected opening. On close: pop stack and check it matches map[c].Step 2: Final check
stack.length === 0 ensures no unmatched opening brackets remain.Why A fails
Only counts, doesn't check types or order.Why C fails
Counter only works for '()' - fails for '([)]' or mixed types.Final Answer:
Option B - map + stack with type checking. -> Option BQuick Check:
Map + stack + empty check at end = correct solution. [OK]
- Using count only (fails mixed brackets)
- Not checking stack empty at end (unmatched opens)
- Not using a map for bracket pairs
Ready to prove it?
Pass the test and this pattern moves unknown
