Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Program to find minimum remove required to make valid parentheses in Python
When working with parentheses validation, we often need to remove the minimum number of invalid parentheses to make a string valid. A string with parentheses is considered valid when every opening parenthesis has a corresponding closing parenthesis in the correct order.
Problem Statement
Given a string containing parentheses '(' and ')' along with lowercase English characters, we need to remove the minimum number of parentheses to make the string valid. A valid parentheses string satisfies these criteria:
The string is empty or contains only lowercase characters, or
The string can be written as AB (A concatenated with B), where A and B are valid strings, or
The string can be written as (A), where A is a valid string.
Algorithm Approach
We'll use a stack-based approach to track unmatched parentheses:
Use a stack to store indices of unmatched opening parentheses
Use a set to store indices of invalid parentheses (both unmatched opening and closing)
Traverse the string and match parentheses pairs
Build the result by excluding invalid parentheses
Implementation
def solve(s):
stack = []
invalid_indexes = set()
# First pass: identify unmatched parentheses
for i, c in enumerate(s):
if c == '(':
stack.append(i)
elif c == ')':
if len(stack) == 0:
# Unmatched closing parenthesis
invalid_indexes.add(i)
else:
# Matched pair, remove opening parenthesis from stack
stack.pop()
# Add remaining unmatched opening parentheses to invalid set
invalid_indexes = invalid_indexes.union(stack)
# Build result string excluding invalid parentheses
result = ''
for i in range(len(s)):
if i not in invalid_indexes:
result += s[i]
return result
# Test the function
s = "m)n(o)p"
print(f"Input: {s}")
print(f"Output: {solve(s)}")
Input: m)n(o)p Output: mn(o)p
Step-by-Step Walkthrough
Let's trace through the example "m)n(o)p":
def solve_with_trace(s):
stack = []
invalid_indexes = set()
print(f"Processing string: {s}")
for i, c in enumerate(s):
print(f"Index {i}, Character '{c}':")
if c == '(':
stack.append(i)
print(f" Added opening at index {i} to stack: {stack}")
elif c == ')':
if len(stack) == 0:
invalid_indexes.add(i)
print(f" Unmatched closing at index {i}, added to invalid: {invalid_indexes}")
else:
popped = stack.pop()
print(f" Matched with opening at index {popped}")
else:
print(f" Regular character, skipping")
print(f"Remaining unmatched opening parentheses: {stack}")
invalid_indexes = invalid_indexes.union(stack)
print(f"All invalid indexes: {invalid_indexes}")
result = ''.join(s[i] for i in range(len(s)) if i not in invalid_indexes)
return result
# Trace example
result = solve_with_trace("m)n(o)p")
print(f"Final result: {result}")
Processing string: m)n(o)p
Index 0, Character 'm':
Regular character, skipping
Index 1, Character ')':
Unmatched closing at index 1, added to invalid: {1}
Index 2, Character 'n':
Regular character, skipping
Index 3, Character '(':
Added opening at index 3 to stack: [3]
Index 4, Character 'o':
Regular character, skipping
Index 5, Character ')':
Matched with opening at index 3
Index 6, Character 'p':
Regular character, skipping
Remaining unmatched opening parentheses: []
All invalid indexes: {1}
Final result: mn(o)p
Time and Space Complexity
Time Complexity: O(n) where n is the length of the string
Space Complexity: O(n) for the stack and invalid indexes set
Conclusion
This stack-based approach efficiently identifies and removes the minimum number of invalid parentheses. The algorithm ensures that all remaining parentheses are properly matched while preserving the original order of characters.
---