Minimum number of bracket reversals needed to make an expression balanced
Problem Statement
Given an expression string containing only { and }, find the minimum number of bracket reversals needed to make the expression balanced.
Example:
-
Input:
"}{" -
Output:
2 -
Explanation: Reverse both brackets to get
{} -
Input:
"{{{{" -
Output:
2 -
Explanation: Reverse last two
{{to}}to get{{}} -
Input:
"{{{{}}" -
Output:
1 -
Explanation: One expression is already balanced, need to reverse one
{to} -
Input:
"}{{}}{{{" -
Output:
3
Note: If string length is odd, it's impossible to balance.
Approach 1: Using Stack
Intuition
First, remove all balanced pairs using a stack. The remaining string will have the form }}}...{{{. We need to reverse these remaining brackets.
Algorithm
- Use stack to remove balanced pairs
- After processing, stack contains unbalanced brackets
- Count remaining
{and}brackets - Calculate reversals needed
import java.util.*;
public class Solution {
public int minReversals(String expr) {
int n = expr.length();
// Odd length can never be balanced
if (n % 2 != 0) {
return -1;
}
Stack<Character> stack = new Stack<>();
// Remove balanced pairs
for (char c : expr.toCharArray()) {
if (c == '{') {
stack.push(c);
} else {
if (!stack.isEmpty() && stack.peek() == '{') {
stack.pop();
} else {
stack.push(c);
}
}
}
// Count unbalanced brackets
int openCount = 0;
int closeCount = 0;
while (!stack.isEmpty()) {
if (stack.pop() == '{') {
openCount++;
} else {
closeCount++;
}
}
return (closeCount + 1) / 2 + (openCount + 1) / 2;
}
}Complexity Analysis
- Time Complexity: O(n) - Single pass through the string
- Space Complexity: O(n) - Stack can hold all characters in worst case
Approach 2: Optimal (Using Counter)
Intuition
We don't need a stack. Just count unmatched brackets using two counters.
Algorithm
- Track count of unmatched opening brackets
- When we see
}, either match with existing{or count as unmatched - Calculate reversals from unmatched counts
public class Solution {
public int minReversals(String expr) {
int n = expr.length();
if (n % 2 != 0) {
return -1;
}
int openCount = 0;
int closeCount = 0;
for (char c : expr.toCharArray()) {
if (c == '{') {
openCount++;
} else {
if (openCount > 0) {
openCount--;
} else {
closeCount++;
}
}
}
return (openCount + 1) / 2 + (closeCount + 1) / 2;
}
}Complexity Analysis
- Time Complexity: O(n) - Single pass
- Space Complexity: O(1) - Only using counters
Understanding the Formula
After removing balanced pairs, we have:
closeCountunmatched}openCountunmatched{
The pattern looks like: }}}...{{{
Why ceil(count/2)?
-
For
}}}}(4 closing):- Reverse 2 to get
{{}}✓ - Reversals = ceil(4/2) = 2
- Reverse 2 to get
-
For
}}}(3 closing):- This is odd, but combined with opening it works
- If we have
}}}{{{→ reverse middle ones →{}{}{} - Reversals needed for }}} part = ceil(3/2) = 2
-
For
{{{{(4 opening):- Reverse 2 to get
{{}}✓ - Reversals = ceil(4/2) = 2
- Reverse 2 to get
-
For
}}{{{:- closeCount = 2, openCount = 3
- Reversals = ceil(2/2) + ceil(3/2) = 1 + 2 = 3
}}{{{→{}{{{→{}{{}}or variations
Edge Cases
Extended: Multiple Types of Brackets
For expressions with (), {}, []:
Key Takeaways
- Remove balanced pairs first to simplify the problem
- After removal, the pattern is
}}}...{{{ - Formula: ceil(close/2) + ceil(open/2)
- Odd length strings can never be balanced
- Space can be optimized from O(n) to O(1) using counters
- This is a classic greedy problem
- The intuition: pair up unmatched brackets and reverse one in each pair
Related Problems
- Minimum Add to Make Parentheses Valid (LeetCode 921)
- Minimum Remove to Make Valid Parentheses (LeetCode 1249)
- Valid Parentheses (LeetCode 20)
- Longest Valid Parentheses (LeetCode 32)