Balanced Parentheses Problem Using Stack in DSA Rust - Time & Space Complexity
We want to know how the time needed to check balanced parentheses grows as the input string gets longer.
How does the program's work increase when the input size increases?
Analyze the time complexity of the following code snippet.
fn is_balanced(s: &str) -> bool {
let mut stack = Vec::new();
for ch in s.chars() {
if ch == '(' || ch == '{' || ch == '[' {
stack.push(ch);
} else {
if stack.is_empty() { return false; }
let top = stack.pop().unwrap();
if !matches!(top, '(' if ch == ')' | '{' if ch == '}' | '[' if ch == ']') {
return false;
}
}
}
stack.is_empty()
}
This code checks if the parentheses in the string are balanced using a stack.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping through each character in the input string once.
- How many times: Exactly once for each character, so n times for input length n.
As the input string gets longer, the program checks each character once, so the work grows directly with input size.
| 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 operations grows linearly as the input size increases.
Time Complexity: O(n)
This means the time to check balanced parentheses grows in direct proportion to the input length.
[X] Wrong: "The time grows faster because of nested checks or multiple passes over the string."
[OK] Correct: The code only loops once through the string, and stack operations are fast, so time grows linearly, not faster.
Understanding this linear time check is a key skill for many coding problems involving stacks and strings. It shows you can reason about efficient solutions.
"What if we changed the input to include other characters besides parentheses? How would the time complexity change?"
Practice
Balanced Parentheses Problem?Solution
Step 1: Understand the role of stack in parentheses matching
A stack stores opening parentheses as they appear to check if each closing parenthesis matches the last opened one.Step 2: Explain why other options are incorrect
Counting, reversing, or sorting parentheses does not help in checking if they are balanced.Final Answer:
To keep track of opening parentheses and match them with closing ones -> Option AQuick Check:
Stack tracks openings for matching = B [OK]
- Thinking stack counts parentheses instead of matching
- Confusing stack with queue for this problem
- Assuming stack sorts parentheses
stack?Solution
Step 1: Recall Rust Vec method to add elements
In Rust,Vecusespush()to add elements at the end.Step 2: Verify other methods are invalid for Vec
add(),insert()require different parameters or do not exist;append()merges vectors, not single elements.Final Answer:
stack.push('('); -> Option BQuick Check:
Vec push method = push() [OK]
- Using append() to add single element
- Confusing insert() with push()
- Using add() which is not a Vec method
fn is_balanced(s: &str) -> bool {
let mut stack = Vec::new();
for ch in s.chars() {
if ch == '(' {
stack.push(ch);
} else if ch == ')' {
if stack.pop().is_none() {
return false;
}
}
}
stack.is_empty()
}
fn main() {
println!("{}", is_balanced("(()())"));
}Solution
Step 1: Trace the input string "(()())" character by character
Process '(', push ['(']; '(', push ['(','(']; ')', pop ['(']; '(', push ['(','(']; ')', pop ['(']; ')', pop []. All match.Step 2: Check final stack state
Stack is NOT empty after processing all 6 characters because the input string "(()())" has 6 characters but the last character is ')', so the stack ends empty. Wait, let's count carefully:
Characters: '(' push ['(']
'(' push ['(','(']
')' pop ['(']
'(' push ['(','(']
')' pop ['(']
')' pop []
Stack is empty after processing all characters, sostack.is_empty()returns true.Final Answer:
true -> Option DQuick Check:
Matched pairs and empty stack = true [OK]
- Mis-counting the number of parentheses
- Ignoring stack emptiness at end
- Confusing pop() returning None with Some
fn check_balance(s: &str) -> bool {
let mut stack = Vec::new();
for ch in s.chars() {
if ch == '(' {
stack.push(ch);
} else if ch == ')' {
stack.pop();
}
}
stack.is_empty()
}Solution
Step 1: Analyze pop() usage on empty stack
The function callsstack.pop()without checking if stack is empty, so popping from empty stack returns None but is ignored.Step 2: Explain consequence of missing check
This causes false positives when closing parentheses appear without matching openings, as function never returns false early.Final Answer:
It does not check if pop() returns None before popping -> Option CQuick Check:
Missing pop() None check causes errors [OK]
- Ignoring pop() returning None on empty stack
- Pushing wrong characters
- Assuming stack emptiness check is enough
"{[(())]}"? The function supports '()', '[]', and '{}' pairs.fn is_balanced(s: &str) -> bool {
let mut stack = Vec::new();
for ch in s.chars() {
if ch == '(' || ch == '[' || ch == '{' {
stack.push(ch);
} else {
if let Some(top) = stack.pop() {
if (ch == ')' && top != '(') ||
(ch == ']' && top != '[') ||
(ch == '}' && top != '{') {
return false;
}
} else {
return false;
}
}
}
stack.is_empty()
}
fn main() {
println!("{}", is_balanced("{[(())]}"));
}Solution
Step 1: Trace the string "{[(())]}" step-by-step
Push '{', '[', '(', '('. Then pop for ')', ')', ']', '}'. Each closing matches the last opening correctly.Step 2: Check stack emptiness after processing
All pairs matched, stack is empty, so function returns true.Final Answer:
true -> Option AQuick Check:
All pairs matched and stack empty = true [OK]
- Not handling multiple bracket types
- Ignoring order of matching pairs
- Forgetting to check stack empty at end
Ready to prove it?
Pass the test and this pattern moves unknown
